Отговори на тема  [ 26 мнения ]  Отиди на страница 1, 2  Следваща
Stop Loop 
Автор Съобщение
Ранг: Минаващ
Ранг: Минаващ
Аватар

Регистриран на: Вто Юни 27, 2017 7:03 am
Мнения: 24
Местоположение: Варна
Мнение Stop Loop
Здравейте
първо да кажа че съм начинаещ в програмиране и постепенно се уча.Захванах се да си направя една уж проста автоматика,а то се оказа голяма греда с този loop.Използвам Arduino като развойна платка.Трябва да се изпълняват следните функции,като само една ми прави проблем и не ми достигат знания за да я реша.

1. натискане и задържане на Бутон UP -->RELAY_UP работи докато се задържа бутон UP
всички други релета са Off
след пускане на бутона всички релета Off

2. натискане и задържане на Бутон DOWN --> RELAY_UP работи 3 сек. и се Off
RELAY_COMPR се On след като RELAY_UP се е Off и работи докато е задържан бутона
RELAY_DOWN да се On 1 сек. след RELAY_COMPR и да работи до пускане на бутона
след пускане на бутона всички релета Off

Имам проблем с това RELAY_UP понеже влиза в цикъл и се On за кратко време когато не трябва.

Това ми е кода
Код:
const int BUTTON_UP = 8;
const int BUTTON_DOWN = 9;
const int RELAY_UP = 2;
const int RELAY_DOWN = 3;
const int RELAY_COMPR = 4;
int BUTTONstate_UP = 0;
int BUTTONstate_DOWN = 0;

void setup() {
  pinMode(BUTTON_UP, INPUT);
  pinMode(BUTTON_DOWN, INPUT);
  pinMode(RELAY_UP, OUTPUT);
  pinMode(RELAY_DOWN, OUTPUT);
  pinMode(RELAY_COMPR, OUTPUT);

}


void loop() {
  BUTTONstate_UP = digitalRead(BUTTON_UP);
  BUTTONstate_DOWN = digitalRead(BUTTON_DOWN);
 
  delay(100);
 
  if (BUTTONstate_UP == HIGH)
  {
   
    digitalWrite(RELAY_UP, HIGH);
  }
  else{
    digitalWrite(RELAY_UP, LOW);
  }
 
 
  if (BUTTONstate_DOWN == HIGH)
  {
   
    digitalWrite(RELAY_UP, HIGH);
    delay(3000);
    digitalWrite(RELAY_UP, LOW);
   
  }

 
  if (BUTTONstate_DOWN == HIGH)
  {
   
    digitalWrite(RELAY_COMPR, HIGH);
   
  }
  else{
   
    digitalWrite(RELAY_COMPR, LOW);
  }
   
  if (BUTTONstate_DOWN == HIGH)
  {
    digitalWrite(RELAY_DOWN, HIGH);
  }
  else{
    digitalWrite(RELAY_DOWN, LOW);
  }
 
}


може би ако по някакъв начин извадя тази част от loop ще заработи както трябва

Код:
if (BUTTONstate_DOWN == HIGH)
  {
   
    digitalWrite(RELAY_UP, HIGH);
    delay(3000);
    digitalWrite(RELAY_UP, LOW);
   
  }


и точно това не знам как да стане.Ще се радвам ако някой може да ми помогне.


Съб Авг 08, 2020 11:55 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: Stop Loop
Трябва ти или запомняне,история, флагове, стейт-машини, броячи за време....
....или по-простичко ...лупове в лупа.

Ако видиш задействан бутон DOWN , (IF DOWN=1 {1.2.3. }
- изпълняваш първата операция 1. релеUP=1 , дилей 3 секунди, изключване
- изпълняваш втората операция 2.релеCOMPR =1 , дилей 1 секунда ,изключване
- включваш реле DOWN и почваш луп 3.- стоиш в него, докато бутонът ти е натиснат.

Последният луп и дилей функциите са ... обичайни за начинаещите.
Направи го така...после мисли как изобщо да нямаш дилей и изчакващи лупове.
По време на тези неща процесорът не прави нищо,не отговаря на външния свят....става така, но за прости неща.


Съб Авг 08, 2020 3:48 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Сеп 26, 2004 8:21 pm
Мнения: 27994
Местоположение: София
Мнение Re: Stop Loop
Този подход станал навик се изкоренява много трудно, лупове, лупчета .... това може да си го позволиш след като си разбрал как се прави със стейтове, никакви лупове, цялата програма ти е един луп, в нея си имаш проверки за определени състояния и флагове за съответните, дали са само флагове или конкретни параметри няма значение, въртиш ифовете, като има нещо което е дошъл момента да се изпълни изпълняваш, променяш съответните стейтове и продължаваш нататък, ако имаш нещо на прекъсване си го обслужваш до колкото е разумно там другото което е неразмно си го изпълняваш отново някъде в основния луп ... като схванеш идеята след това пиши както искаш, лошото е ако никога не схванеш идеята, лично мое мнение ако искаш да се занимаваш с ембедед.


Съб Авг 08, 2020 4:01 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: Stop Loop
Абсолютно си прав....
само дето трудно се скача отвисоко ,,,първия път. :D


Съб Авг 08, 2020 4:17 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Сря Сеп 28, 2011 9:04 am
Мнения: 38
Мнение Re: Stop Loop
koko76bj написа:
Здравейте
първо да кажа че съм начинаещ в програмиране и постепенно се уча.Захванах се да си направя една уж проста автоматика,а то се оказа голяма греда с този loop.Използвам Arduino като развойна платка.Трябва да се изпълняват следните функции,като само една ми прави проблем и не ми достигат знания за да я реша.

1. натискане и задържане на Бутон UP -->RELAY_UP работи докато се задържа бутон UP
всички други релета са Off
след пускане на бутона всички релета Off

2. натискане и задържане на Бутон DOWN --> RELAY_UP работи 3 сек. и се Off
RELAY_COMPR се On след като RELAY_UP се е Off и работи докато е задържан бутона
RELAY_DOWN да се On 1 сек. след RELAY_COMPR и да работи до пускане на бутона
след пускане на бутона всички релета Off

Имам проблем с това RELAY_UP понеже влиза в цикъл и се On за кратко време когато не трябва.

Това ми е кода
Код:
const int BUTTON_UP = 8;
const int BUTTON_DOWN = 9;
const int RELAY_UP = 2;
const int RELAY_DOWN = 3;
const int RELAY_COMPR = 4;
int BUTTONstate_UP = 0;
int BUTTONstate_DOWN = 0;

void setup() {
  pinMode(BUTTON_UP, INPUT);
  pinMode(BUTTON_DOWN, INPUT);
  pinMode(RELAY_UP, OUTPUT);
  pinMode(RELAY_DOWN, OUTPUT);
  pinMode(RELAY_COMPR, OUTPUT);

}


void loop() {
  BUTTONstate_UP = digitalRead(BUTTON_UP);
  BUTTONstate_DOWN = digitalRead(BUTTON_DOWN);
 
  delay(100);
 
  if (BUTTONstate_UP == HIGH)
  {
   
    digitalWrite(RELAY_UP, HIGH);
  }
  else{
    digitalWrite(RELAY_UP, LOW);
  }
 
 
  if (BUTTONstate_DOWN == HIGH)
  {
   
    digitalWrite(RELAY_UP, HIGH);
    delay(3000);
    digitalWrite(RELAY_UP, LOW);
   
  }

 
  if (BUTTONstate_DOWN == HIGH)
  {
   
    digitalWrite(RELAY_COMPR, HIGH);
   
  }
  else{
   
    digitalWrite(RELAY_COMPR, LOW);
  }
   
  if (BUTTONstate_DOWN == HIGH)
  {
    digitalWrite(RELAY_DOWN, HIGH);
  }
  else{
    digitalWrite(RELAY_DOWN, LOW);
  }
 
}


може би ако по някакъв начин извадя тази част от loop ще заработи както трябва

Код:
if (BUTTONstate_DOWN == HIGH)
  {
   
    digitalWrite(RELAY_UP, HIGH);
    delay(3000);
    digitalWrite(RELAY_UP, LOW);
   
  }


и точно това не знам как да стане.Ще се радвам ако някой може да ми помогне.



Много ми е трудно да разбера какво е имал в предвид автора като задание. Пускам ти един пример какво бих направил аз.
Нещо се загубих в описанието но принципа е този , просто разшири стейт машината
Код:
inline const int BUTTON_UP = 8;
inline const int BUTTON_DOWN = 9;
inline const int RELAY_UP = 2;
inline const int RELAY_DOWN = 3;
inline const int RELAY_COMPR = 4;

auto setup () ->void
{
    pinMode(BUTTON_UP, INPUT);
    pinMode(BUTTON_DOWN, INPUT);
    pinMode(RELAY_UP, OUTPUT);
    pinMode(RELAY_DOWN, OUTPUT);
    pinMode(RELAY_COMPR, OUTPUT);
}



auto loop() ->void
{
    static long start_ticks= 0 ;
    static enum class EState
    {
        Init,
        Idle,
        Relay1On,
        Relay1Off,
        Relay2Start,
        Relay2WaitUntil,
        Relay2Stop,
    } state = EState::Init;

    auto but_up = digitalRead(BUTTON_UP);
    auto but_dn = digitalRead(BUTTON_DOWN);
    static auto last_but_up = but_up;
    static auto last_but_dn = but_dn;


    // button up - detect state changed
    if ( but_up != last_but_up)
    {
        last_but_up = but_up;
        state = (but_up == true) ? EState::Relay1On : EState::Relay1Off;
    }

    // button dn - detect state changed
    if ( but_dn != last_but_dn)
    {
        last_but_dn = but_dn;
        state = (but_dn == true) ? EState::Relay2Start : EState::Relay2Stop;
    }

    // state machine

    switch (state)
    {

    case EState::Init:
        digitalWrite (RELAY_COMPR ,false );
        digitalWrite (RELAY_UP ,false );
        state = EState::Idle;

    case EState::Idle:
        break;

    case EState::Relay1On:
        digitalWrite (RELAY_COMPR ,true );
        state = EState::Idle;
        break;

    case EState::Relay1Off:
        digitalWrite (RELAY_COMPR ,false);
        state = EState::Idle;
        break;

    case EState::Relay2Start:
        digitalWrite (RELAY_UP ,true );
        start_ticks = xTaskGetTickCount();
        state = EState::Relay2WaitUntil;

    case EState::Relay2WaitUntil:
        if ((xTaskGetTickCount() - start_ticks )< 3000) break;
        digitalWrite (RELAY_UP ,false );
        digitalWrite (RELAY_COMPR  ,true );
        state = EState::Idle;
        break;

    case EState::Relay2Stop:
        digitalWrite (RELAY_COMPR  ,false );
        state = EState::Idle;
        break;
    };

    vTaskDelay(1);

}

Пооправи си малко синтаксисът - това е на C++ с FreeRTOS
Никога не съм бачкал с Ардуино, а с 'C' много отгавна
идеята е, че помниш статуса на бутоните и при промяна изпълняваш съответният state . Мисля , че това ще ти свърши работа.
потърси с кои функции можеш да смениш xTaskGetTickCount и vTaskDelay
Поздрави

_________________
Оставете човек в самолет и той ще летне за един ден.
Хвърлете човек от самолета и той лети до края на живота си.


Последна промяна panchev68 на Съб Авг 08, 2020 6:07 pm, променена общо 1 път



Съб Авг 08, 2020 5:29 pm
Профил ICQ
Ранг: Минаващ
Ранг: Минаващ
Аватар

Регистриран на: Вто Юни 27, 2017 7:03 am
Мнения: 24
Местоположение: Варна
Мнение Re: Stop Loop
Промених кода както ме посъветвахте

Код:
#define button_up 8
#define button_down 9
#define relay_up 2
#define relay_compr 3
#define relay_down 4

int BUTTONstate_UP = 0;
int state = 0;
int old = 0;
int buttonPoll = 0;

void setup() {

pinMode(button_up,INPUT);
pinMode(button_down,INPUT);
pinMode(relay_up,OUTPUT);
pinMode(relay_compr,OUTPUT);
pinMode(relay_down,OUTPUT);

digitalWrite(relay_up,LOW);
digitalWrite(relay_compr,LOW);
digitalWrite(relay_down,LOW);

}

void loop() {

BUTTONstate_UP = digitalRead(button_up);

  if (BUTTONstate_UP == HIGH)
  {
   
    digitalWrite(relay_up, HIGH);
  }

 
buttonPoll = digitalRead(button_down);
if(buttonPoll == 1){
  delay(50);
  buttonPoll = digitalRead(button_down);
  if(buttonPoll == 0){
    state = old + 1;
  }
}
else{
  delay(100);
}
switch (state) {
  case 1:
  digitalWrite(relay_up,HIGH);
  digitalWrite(relay_compr,LOW);
  digitalWrite(relay_down,LOW);
  old = state;
  break;

  case 2:
  digitalWrite(relay_up,LOW);
  digitalWrite(relay_compr,HIGH);
  digitalWrite(relay_down,LOW);
  old = state;
  break;

  case 3:
  digitalWrite(relay_up,LOW);
  digitalWrite(relay_compr,HIGH);
  digitalWrite(relay_down,HIGH);
  old = state;
  break;

  default:
  digitalWrite(relay_up,LOW);
  digitalWrite(relay_compr,LOW);
  digitalWrite(relay_down,LOW);
  old = 0;
  break;
 
 
}
}


със всяко натискане на бутона down се променя състоянието.Но си зададох въпроса удачно ли е да е така.


Съб Авг 08, 2020 6:07 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Сря Сеп 28, 2011 9:04 am
Мнения: 38
Мнение Re: Stop Loop
виж PM
Няма много разлика от 1-вата ти версия
Цитат:
Идеята е, че помниш статуса на бутоните и при промяна изпълняваш съответният state

Не зная с тоя delay (100); какво точно имаш в предвид

_________________
Оставете човек в самолет и той ще летне за един ден.
Хвърлете човек от самолета и той лети до края на живота си.


Последна промяна panchev68 на Съб Авг 08, 2020 6:15 pm, променена общо 1 път



Съб Авг 08, 2020 6:10 pm
Профил ICQ
Ранг: Минаващ
Ранг: Минаващ
Аватар

Регистриран на: Вто Юни 27, 2017 7:03 am
Мнения: 24
Местоположение: Варна
Мнение Re: Stop Loop
panchev68 написа:
виж PM


видях поста ви колега,но този език ми е непознат все още.Ще се постарая да го разбера и да хвана логиката.


Съб Авг 08, 2020 6:14 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Сря Сеп 28, 2011 9:04 am
Мнения: 38
Мнение Re: Stop Loop
koko76bj написа:
panchev68 написа:
виж PM


видях поста ви колега,но този език ми е непознат все още.Ще се постарая да го разбера и да хвана логиката.


ок успех

_________________
Оставете човек в самолет и той ще летне за един ден.
Хвърлете човек от самолета и той лети до края на живота си.


Съб Авг 08, 2020 6:16 pm
Профил ICQ
Ранг: Минаващ
Ранг: Минаващ
Аватар

Регистриран на: Вто Юни 27, 2017 7:03 am
Мнения: 24
Местоположение: Варна
Мнение Re: Stop Loop
Цитат:
Идеята е, че помниш статуса на бутоните и при промяна изпълняваш съответният state


Идеята е с постоянно натиснат бутон down се си извърта всички state и да остане на последния до пускането на бутона или ако бутона се пусне някъде другаде от цикъла веднага всичко да е Off

Цитат:
Не зная с тоя delay (100); какво точно имаш в предвид
[/quote]

задържам малко заради трепването което се получава при превключването на бутона,иначе се получава малко хаус в работата и прескача state.


Съб Авг 08, 2020 6:33 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: Stop Loop
Ако много бързаш - направи го с лупчета.
Ако не бързаш - представи си ,че 3те релета и 2та бутона са само 1/10 от всичко в ТВОЯТА система,,,,и трябва да обслужваш
още 9/10 .
Тогава тая 1/10 подистема я разглеждаш като нещо , което си има текущо сътояние и трябва да реагира на промени в средата.
Няма значение колко променливи ще трябва да дефинираш, това е пътят.

Обучението по програмиране обикновено включва съставяне на блок-схеми....обаче система със състояния ,памет - малко трудно се представя с блок схема. Та ....не бързай ,мисли и питай. И запомни, че много трудно се чете чужд код повече от 20реда.


Съб Авг 08, 2020 8:20 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 20, 2005 11:02 am
Мнения: 8888
Местоположение: Разград
Мнение Re: Stop Loop
Учжд, аз след 2 години моя не мога да чета ти за чужд говориш. Рисуването на блок схема понякога помага. Някой път не мога да "видя" алгоритъма и ако дълго време не успявам да го видя - почвам да рисувам - някой път помага.


Съб Авг 08, 2020 9:15 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Сеп 26, 2004 8:21 pm
Мнения: 27994
Местоположение: София
Мнение Re: Stop Loop
Абе в момента съм на съвсем друга вълна и не съм гледал кодовете, но както Стефан е писал, идеята е че имаш състояния, затова и се нарича state machine. Имаш определени състояния за отделните подсистеми. Най-просто, имаш светодиод имаш бутон. Бутона като вход може да има две състояния, 0/1 диода като изход също. В същото време обаче тези и двете може да имат и други състояния/статуси, свързани с тяхното функциониране. Примерно бутона при продължително натискане влиза в състояние задаване интервал честота на мигане, съответно при следващото дълго излиза от това състояние, а при кратки натискания вкл/изкл. светодиода или променя честотата с една стъпка. В този случай примерно дебоунсинга го правиш на база състоняието на входа, абстрахирай се от това дали е истински вход или твой флаг. Това са няколко прости стейт машини с по две състояния, в този случай вместо switch case може да използваш if. Съответно имаш флаг който казва бутона е натиснат, това е състояние в което бутона преминава от 1 в 0. Отделно имаш флаг/състояние което казва бутона е бил натиснат късо или пък дълго, което съответно определяш по това колко време е минало от натискането на бутона до неговото отпускане. Отделно знаеш кога бутона е отпуснат. Да речем ако времето е по-малко от 200 мс, приемаш че е смущения, тогава нулираш флага указващ че бутона е бил натиснат и чакаш следващо натискане. Ако времето е между 200 и 500 мс, приемаш че бутона е натиснат т.е. дигаш флаг valid_button и нямаш промяна във функционалното състояние. Ако времето е приметно 1000 мс казваш че стейта на функцията на бутона е дълго натискане.
След това когато проверяваш флага valid_button в случай че е вдигнат първо правиш switch / case на функцията на бутона, ако приемем че имаш два режима може да го направиш с if, обаче бутона може да има и 10 режима, съответно в тоя случай switch / case е по-удачния вариант. Така ако да речем стейта е 0, инвертираш флага за състояние на леда съответно той се вкл. или изключва, ако стейта е 1 отиваш на следващата стъпка на честотата за мигане, ако е 2 пък може да правиш нещо друго и т.н.
Малко трудно се описва нещо което трябва да се начертае или пък да се напише като код ... не знам дали схвана идеята.
Естествено много от тия неща, особено свързани с бутони, дебонсинг и т.н. могат да се реализират в голяма степен хардеурно, примерно вместо да проверяваш постоянно бутона дали е натиснат или отпуснат, чакаш съответното прекъсване прекъсване, вместо да проверяваш постоянно някакъв таймер може и той да е на прекъсване като така ти остава време да правиш и други неща.
Докато правиш 1-2 неща много по лесен изглежда подхода с лупове и някакви фиксирани състояния, но когато нещата започнат да стават повече това спира да работи. Не можеш да въртиш в някакъв луп чакайки някой да отпусне или натисне бутона защото ще трябва да вършиш и други неща, примерно ако диода не свети постоянно а мига ще трябва да го мигаш и т.н. ...
Та моя съвет е макар и да изглежда по-трудно опитай да пишеш код без лупове, освен main луп избягвай други лупове, особено пък такива от които нямаш надежден изход.

п.с. това че скачаш е нормално, за да не се получава трябва да правиш дебонсинг. Не знам дали нямаш някаква стандартна функция за това в Ардуиното, но винаги е по-добре да знаеш как да си го направиш. В зависимост как работиш имаш много варианти за дебонсинг, ако имаш само полиране както по горе ти писах направи си флаг, button-poressed, button_valid преди да вдигнеш втория чакаш да мине известно време, ако бутона се отпусне може да нулираш първия, т.е. да започне да тече отново дебонсинг тайма, или просто проверяваш чак след като изтече времето и ако е още натиснат вдигаш button_valid. Сега най-удачно е използването на системен таймер, когато ти станат повече неща трудно ще е да водиш отделни броячи за всяко, освен ако не си съвсем на границите на ресурсите подобре е да сравняваш тайм стамп който си взел при възникване на събитието с текущо време.


Съб Авг 08, 2020 9:27 pm
Профил
Ранг: Ориентиран
Ранг: Ориентиран

Регистриран на: Вто Май 07, 2019 8:16 pm
Мнения: 277
Мнение Re: Stop Loop
Може секвенциално(стейт машини), може комбинаторно и всякак. Ако съм разбрал питащия правилно, иска да реализира някаква такава фунция:
Прикачени файлове:
funct.jpg
funct.jpg [ 72.08 KiB | Прегледано 4505 пъти ]


която би се емулирала в Ардуиното с някакъв такъв код:
Код:
boolean A=0,  B=0, B_OLD=0, B_PRIME;  boolean Y1, Y2, Y3;
  unsigned long TimeStamp=0;

  void setup() {
     pinMode(2, INPUT); pinMode(3,INPUT);
     pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT);
  }
 
 
  void loop()  {
 
    A=digitalRead(2); B=digitalRead(3);
 
    if (B != B_OLD)  { TimeStamp=millis(); B_OLD=B; }
 
    B_PRIME = (B & !(millis() > (TimeStamp+3000)));
    Y1=(A | B_PRIME); digitalWrite(4, Y1);
    Y2=(!B_PRIME & B); digitalWrite(5, Y2);
    Y3=(Y2 & (millis() > (TimeStamp+4000))); digitalWrite(6, Y3);
 
  }


с уговорката че не съм писал за Ардуино от години и сигурно има нужда от някакви дооправки. Пин 2 и 3 са бутоните. Пин 4,5 и 6 са релетата.


Нед Авг 09, 2020 12:46 pm
Профил
Ранг: Минаващ
Ранг: Минаващ
Аватар

Регистриран на: Вто Юни 27, 2017 7:03 am
Мнения: 24
Местоположение: Варна
Мнение Re: Stop Loop
Здравейте
първо искам да изкажа благодарности на всички за съветите,препоръките и примерите.Кода е написан благодарение на огромната помощ на колегата panchev68 за което много му благодаря =D> .Много хубаво обяснява и показва.Тези дни ще направя платка и ще се тества в реални работни условия.
Благодаря ви!


Пон Авг 10, 2020 6:44 am
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 26 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 4 госта


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

Търсене:
Иди на:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни