Нужна помощь по остановке выполнения функции если начальное условие сменилось!

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

Всем привет! Помогите разобраться люди добрые, как сделать прерывание функций во время работы устройства. Принцип такой: "клацаем" левый поворотник без его фиксации, выполняется команда включения с задержкой на 3 секунды, аналогично работают правый поворот и "Аварийка", НО тут засада, например в некоторых моментах нужно резко переключиться с левого поворота на правый и наоборот, но Ардуино пока не отработает задержку в 3сек не принимает новых команд....

Скетч с коментариями прилагается:

//"Лентяйка" на поворотники с функцией "Спасибо" для машин где управление идет по "+".

// Выставляем пины контроллера "Arduino UNO"
// Входы
int LTSPin = 8; // Левая сторона "Left Turn Signal"
int RTSPin = 9; // Правая сторона "Right Turn Signal"
int ALLTSPin = 10; // "Аварийка" "ALL Turn Signal"
// Выходы
int LTOPin = 11; // Левая сторона "Left Turn Out"
int RTOPin = 12; // Правая сторона "Right Turn Out"

int pause = 3000; // Переменная паузы включения

void setup() {
  // Выставляем входы/выходы
  pinMode(LTSPin, INPUT);
  pinMode(RTSPin, INPUT);
  pinMode(ALLTSPin, INPUT);
  pinMode(LTOPin, OUTPUT);
  pinMode(RTOPin, OUTPUT);
}

void loop() {
  byte LTState = 0; // Состояние левого сигнала - локальная переменная!
  byte RTState = 0; // Состояние правого сигнала - локальная переменная!
  byte ALLTState = 0; // "Аварийка" - локальная переменная!

  // Считываем состояние входов
  LTState = digitalRead(LTSPin); 
  RTState = digitalRead(RTSPin);
  ALLTState = digitalRead(ALLTSPin);

  // Левый поворот
  if (LTState == 1) { // Проверяем состояние, включен ли левый поворот
    if (RTState == 0) { // Проверяем состояние, включен ли правый поворот
      LTurn(); // Вызываем функцию левый поворот ВКЛ
      RTurnOFF(); // Вызываем функцию правый поворот ВЫКЛ
    }
    else {
      LTurnOFF(); // Вызываем функцию левый поворот ВЫКЛ 
    }
  }
  // Правый поворот
  else if (RTState == 1) { // Проверяем состояние, включен ли правый поворот
    if (LTState == 0 ) { // Проверяем состояние, включен ли левый поворот
      RTurn(); // Вызываем функцию правый поворот ВКЛ
      LTurnOFF(); // Вызываем функцию левый поворот ВЫКЛ
    }
    else {
      RTurnOFF(); // Вызываем функцию правый поворот ВЫКЛ  
    }
  }
  // "Аварийка"
  else if (ALLTState == 1) { // Проверяем состояние, включена ли "Аварийка"
    ALLTurn(); // Вызываем функцию "Аварийка" ВКЛ
  }
  else {
    ALLTurnOFF(); // Вызываем функцию "Аварийка" ВЫКЛ 
  }

}

// Функции левый поворот
void LTurn () {
    digitalWrite(LTOPin, HIGH);
    delay (pause);
    digitalWrite(LTOPin, LOW);
}
void LTurnOFF() {
    digitalWrite(LTOPin, LOW);
}

// Функции правый поворот
void RTurn () {
    digitalWrite(RTOPin, HIGH);
    delay (pause);
    digitalWrite(RTOPin, LOW);
}
void RTurnOFF() {
    digitalWrite(RTOPin, LOW);
}

// Функции "Аварийка"
void ALLTurn () {
    digitalWrite(LTOPin, HIGH);
    digitalWrite(RTOPin, HIGH);
    delay (pause);
    digitalWrite(LTOPin, LOW);
    digitalWrite(RTOPin, LOW);
}
void ALLTurnOFF() {
    digitalWrite(LTOPin, LOW);
    digitalWrite(RTOPin, LOW);
}

 

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

Ну так избавляйтесь от delay().

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

Вместо 

delay (pause);

везде пишите

for (int i=0; i < pause; i++) {
   if (<УСЛОВИЕ ШУХЕРА>) return;
   delay(1);
}

Что там за "условие шухера" у Вас я не знаю, пропишете по какому именно условию нужно из функции срочно выпрыгивать.

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

andriano, я не так давно начал разбираться в программировании, обычно переделывал готовые скетчи или использовал библиотеки, а вот с таким за пол года впервые столкнулся... ибо никто такое устройство на ардуино не делал... поэтому решил попросить помощи ибо я уже с этим скетчем муздохаюсь вторые сутки, не выдержал! )

ЕвгенийП, спасибо, попробую переделать!

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

andriano, читал я уже это и даже пробовал, я же не с фонаря решил тему создать, я сначала по гуглу прошелся форумы почитал, из того что мне нужно либо на чисто С написано либо на Ассемблере, а я в них полный ноль..... но всеравно спасибо.

ЕвгенийП, попробовал, переделал эффект тот же, пока функция не досчитает условие до нужного значения, к другой не переходит, как бы так объяснить.... в общем, есть два выключателя и две лампочки, нужно сделать так чтобы каждый выключатель включал свою лампочку, НО если при включении первого вторая лампочка горит, то ее гасить и наоборот.

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

Ошибка не в программе. Ошибка в самом алгоритме.

Есль три кнопки : левый поворот , правый поворот и аварийка

И 4 состояния: ничего не мигает, правая мигает, левая мигает, правая и левая мигает.

На деле надо 2 вычислительных потока: 1)-сьем информации с кнопки и выдача состояния 0,1,2,3 и 2) - отработка этого состояния 0,1,2,3  не мигать, мигать одним, мигать другим , мигать обеими фарами.

/*
#1
светодиод 1 ->11 (LTO_pin) левый   1 горит/ 0 нет
светодиод 2 ->12 (RTO_pin) правый  1 горит/ 0 нет
#2
кнопка 1 -> 8 (LTS_pin)    левый поворот 0 нажата /1 нет
кнопка 2 -> 9 (RTS_pin)    правый поворот 0 нажата/ 1 нет
кнопка 3 -> 10 (ALLTS_pin) авария 0 нажата /1 нет
*/
//#1
const int LTO_pin = 11; // Левая сторона "Left Turn Out"
const int RTO_pin = 12; // Правая сторона "Right Turn Out"
int stat = 0; // 0 не горит / 1 правая мигает / левая мигает / 2 обе мигают
const int pause = 3000; // Переменная паузы включения
//#2
const int LTS_pin = 8    ; // Левая сторона "Left Turn Signal"
const int RTS_pin = 9    ; // Правая сторона "Right Turn Signal"
const int ALLTS_pin = 10 ; // "Аварийка" "ALL Turn Signal"
bool LTState ; // Состояние левого сигнала - локальная переменная!
bool RTState ; // Состояние правого сигнала - локальная переменная!
bool ALLTState ; // "Аварийка" - локальная переменная!
void setup() {
  //#1
  pinMode(LTO_pin, OUTPUT);
  pinMode(RTO_pin, OUTPUT);
  //#2
  pinMode(LTS_pin, INPUT_PULLUP);
  pinMode(RTS_pin, INPUT_PULLUP);
  pinMode(ALLTS_pin, INPUT_PULLUP);
}

void loop() {
  //#1 мигалка
  static uint32_t past_1 = 0 ;
  if (millis() - past_1 >= 200) { // если прошло 200 миллисек
    past_1 = millis() ;
    switch (stat) {
      case 0: // "Обычный ход"
        digitalWrite(LTO_pin, 0);
        digitalWrite(RTO_pin, 0);
        break;
      case 1: // Левый поворот
        digitalWrite(LTO_pin, millis()% pause <pause/2);
        digitalWrite(RTO_pin, 0);
        break;
      case 2: // Правый поворот
        digitalWrite(LTO_pin, 0);
        digitalWrite(RTO_pin, millis()% pause <pause/2);
        break;
      case 3:  // "Аварийка"
        digitalWrite(LTO_pin, millis()% pause <pause/2);
        digitalWrite(RTO_pin, millis()% pause <pause/2);
        break;
    }
  }
  //#2 кнопки
  LTState  = digitalRead(LTS_pin);
  RTState  = digitalRead(RTS_pin);
  ALLTState = digitalRead(ALLTS_pin);
  if (!LTState && RTState)       // Левый поворот
    stat = 1;
  else if (LTState && ! RTState) // Правый поворот
    stat = 2;
  else if (! ALLTState)        // "Аварийка"
    stat = 3;
  else stat = 0;         // "Обычный ход"
}

В работе код не проверял.

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

qwone, спасибо за наводку, суть уловил, буду пробовать, но завтра на свежую голову, ибо когда долго ковыряешься мозг отключается! )

Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

CarismaGLX пишет:

Ардуино пока не отработает задержку в 3сек не принимает новых команд....


Они такие, как напишешь так и работают, никакого творчества от них не дождешься...

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

CarismaGLX пишет:

ЕвгенийП, попробовал, переделал эффект тот же, пока функция не досчитает условие до нужного значения, к другой не переходит, 

Значит, не так переделпли или с улсовием напутали. Не работать оно не может, там нечему не работать.

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013
//"Лентяйка" на поворотники с функцией "Спасибо" для машин где управление идет по "+".

// Выставляем пины контроллера "Arduino UNO"
// Входы
int LTSPin = 8; // Левая сторона "Left Turn Signal"
int RTSPin = 9; // Правая сторона "Right Turn Signal"
int ALLTSPin = 10; // "Аварийка" "ALL Turn Signal"
// Выходы
int LTOPin = 11; // Левая сторона "Left Turn Out"
int RTOPin = 12; // Правая сторона "Right Turn Out"

int pause = 3000; // Переменная паузы включения

void setup() {
  // Выставляем входы/выходы
  pinMode(LTSPin, INPUT);
  pinMode(RTSPin, INPUT);
  pinMode(ALLTSPin, INPUT);
  pinMode(LTOPin, OUTPUT);
  pinMode(RTOPin, OUTPUT);
}

void loop() {
  byte LTState = 0; // Состояние левого сигнала - локальная переменная!
  byte RTState = 0; // Состояние правого сигнала - локальная переменная!
  byte ALLTState = 0; // "Аварийка" - локальная переменная!

  // Считываем состояние входов
  LTState = digitalRead(LTSPin); 
  RTState = digitalRead(RTSPin);
  ALLTState = digitalRead(ALLTSPin);

  // Левый поворот
  if (LTState == 1) { // Проверяем состояние, включен ли левый поворот
    for (int i=0; i < pause; i++) {
        if (RTState == 1) return;
        LTurn();
        delay(1);
    }
  }
  // Правый поворот
  else if (RTState == 1) { // Проверяем состояние, включен ли правый поворот
    for (int i=0; i < pause; i++) {
        if (LTState == 1) return;
        RTurn();
        delay(1);
    }
  }
  // "Аварийка"
  else if (ALLTState == 1) { // Проверяем состояние, включена ли "Аварийка"
    ALLTurn(); // Вызываем функцию "Аварийка" ВКЛ
  }
  else {
    ALLTurnOFF(); // Вызываем функцию "Аварийка" ВЫКЛ 
  }

}

// Функции левый поворот
void LTurn () {
    digitalWrite(LTOPin, HIGH);
}
void LTurnOFF() {
    digitalWrite(LTOPin, LOW);
}

// Функции правый поворот
void RTurn () {
    digitalWrite(RTOPin, HIGH);
}
void RTurnOFF() {
    digitalWrite(RTOPin, LOW);
}

// Функции "Аварийка"
void ALLTurn () {
    digitalWrite(LTOPin, HIGH);
    digitalWrite(RTOPin, HIGH);
}
void ALLTurnOFF() {
    digitalWrite(LTOPin, LOW);
    digitalWrite(RTOPin, LOW);
}

 

Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

Вот еще до скетча мой хрустальный шар показывал что ТС читал не пины а переменные...

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

Ну, правильно. Чего Вы написали то? Вот взять строки 43-47. Вы крутитесь в цикле до тех пор пока либо не закончится цикл, либо переменная LTState не станет равной 1. Скажите мне, каким образом она станет 1? Кто и когда её сделает 1 в этом цикле? Никто и никогда. Напишите нормальное условие и будет счастье.

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

Посмотрите и такой код дя общего развития


#include <arduino.h>
/*
 Реле поворотов
 */
#define Left 8
#define Rift 9
#define Avar 10
#define led_Left 11
#define led_Rift 12
#define pause 250 //Период мигания
unsigned long currentPause;
bool fl_pause;
bool fl_sost = 0;
bool blik = LOW;
int perem = 0;

void setup()
{
    pinMode(Left, INPUT);
    pinMode(Rift, INPUT);
    pinMode(Avar, INPUT);
    pinMode(led_Left, OUTPUT);
    pinMode(led_Rift, OUTPUT);
}

//Создаем генератор миганий
void my_pausa()
{
    if (fl_pause == 0)currentPause = millis(), fl_pause = 1;
    if (millis() - currentPause >= pause) blik = !blik, fl_pause = 0;
}

void loop()
{
    if(digitalRead(Left))perem = 1;
    else if (digitalRead(Rift))perem = 2;
    else if (digitalRead(Avar))perem = 3;
    else
    {
        perem = 0;
        if(fl_sost)
        {
            digitalWrite(led_Left, LOW);
            digitalWrite(led_Rift, LOW);
            fl_sost = 0;
        }
    }

    if (perem)
    {
        my_pausa();
        fl_sost = 1;
        switch (perem)
        {
        case 1:
            digitalWrite(led_Left, blik);
            break;
        case 2:
            digitalWrite(led_Rift, blik);
            break;
        case 3:
            digitalWrite(led_Left, blik);
            digitalWrite(led_Rift, blik);
        }
    }
}

 

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

ЕвгенийП, так это же переменная получаемая при нажатии кнопки.... или я туплю совсем?

vosara, спасибо Вам попробую и этот, в любом случае при помощи или без помощи если разберусь отпишу здесь и выложу рабочий код, чтобы люди так же не мучались если будут искать!

 

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

CarismaGLX пишет:

ЕвгенийП, так это же переменная получаемая при нажатии кнопки.... или я туплю совсем?

Я не знаю, тупите Вы или нет. Я вам задал простой вопрос: "Скажите мне, каким образом она станет 1? Кто и когда её сделает 1 в этом цикле?" Так ответьте ж на него. Себе в первую очередь. Только без общих теорий, а точно и чётко: "Эта переменная станет 1 в строке № при таком-то условии".

А потом подумайте, а в тот момент, когда программа крутится в цикле, она может в эту саму строку № попасть?

Подумайте.

Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

Почему то новички очень часто думают что переменные ВСЕГДА равны состоянию пинов. И не важно где они их приравняли. Нужно уже сделать такой тип данных pin который равен пину в реальном времени (или почти).

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

ЕвгенийП, Mr.Privet, ну что поделать товарищи, не все сразу стали гуру, я же не злюсь когда меня как электрика 4-го разряда спрашивают, а как подключить розетку, не правда ли тупой вопрос? Тут уж кто чем занимается, так что от этого не уйти.... А работа над ошибками проведется, спасибо за помощь!

Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

CarismaGLX пишет:

ЕвгенийП, Mr.Privet, ну что поделать товарищи, не все сразу стали гуру...


Не стали, а некоторые не хотят и не чешатся. Но к вам это не относится, это я про других. Если продолжите разбираться с Ардуино через годик сами посмеетесь над своими постами. Вы поняли где у вас была ошибка? Давайте пробежимся: комментарии к коду в 10 посту: в строках 29, 30, 31 Вы правильно присваиваете переменным состояние пинов. У Вас кнопки "считываются" только там. Но в ифах вы уже работаете с переменными, то есть условия на вылет из цикла у Вас зависят от переменной, которая может измениться только в строках 29,30,31 грубо говоря переменная не обновляется. Если писать не
if (RTState == 1) return а if (digitalRead(RTSpin== 1)) return то будет Вам счастье. Ну или все это напрашивается на цыкл while{}. Как домашнее задание подумайте что будет если зажать две кнопки левого и правого поворота. Вообще данную задачу правильнее решать как сказал Винни Пух

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

Mr.Privet, именно код Винни я и взял в пример, а моя ошибка в том что я как Вы сказали думал что приоритет у команды считывания кнопки... так что вечерком, после работы покумекаю еще, как реализую "правильную" работу системы, скину код еще раз, может что-то оптимизировать получиться, ибо мне это все запихнуть в Тиньку13 надо, а там памяти с горошину! ))

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

В общем долго я "кумекал", перечитал кучу всего, собрал "франкинштейна", повороты работают как мне надо, за исключением того что не могу организовать одновременную работу левого и правого ("аварийку"), ибо они друг друга "тушат", есть ли возможность "подружить" обе стороны не в ущерб фунционалу? Ну может еще помидорками покидаетесь! )))

// Комфортные поворотники "Лентяйка" с фунцией "Спасибо"

// Входы
int LeftBut = 8; // Левая сторона "Left Turn Signal"
int RightBut = 9; // Правая сторона "Right Turn Signal"
// Выходы
int LeftOUT = 11; // Левая сторона "Left Turn Out"
int RightOUT = 12; // Правая сторона "Right Turn Out"

byte LbState = 0; // Переменная левой кнопки
byte RbState = 0; // Переменная правой кнопки

//Переменные для хранения значений счетчиков
unsigned long LOnTime;
unsigned long ROnTime;

int pause = 2000; // Переменная паузы включения

// Переменные для хранения состояния кнопок
bool LTstate;
bool RTstate;

void setup() {
  // Выставляем входы/выходы
  pinMode(LeftBut, INPUT);
  pinMode(RightBut, INPUT);
  pinMode(LeftOUT, OUTPUT);
  pinMode(RightOUT, OUTPUT);
  // Сбрасываем состояния кнопок
  LTstate = false;
  RTstate = false;
}

void loop() {
  // Считываем состояние входов
  LbState = digitalRead(LeftBut); 
  RbState = digitalRead(RightBut);
  byte state = RbState*2+LbState; // Переменная общего состояния входов

// Левый поворот
  if (state==1) {
    digitalWrite(LeftOUT, HIGH);
    digitalWrite(RightOUT, LOW);
    LTstate = true; // Активируем таймер левого поворота
    LOnTime = millis(); // Переменная начала отсчтета таймера
  }
  
// Правый поворот
  if (state==2) {
    digitalWrite(RightOUT, HIGH);
    digitalWrite(LeftOUT, LOW);
    RTstate = true; // Активируем таймер правого поворота
    ROnTime = millis(); // Переменная начала отсчтета таймера
  }
  
// "Аварийка"
  if (state==3) {
    digitalWrite(LeftOUT, HIGH);
    digitalWrite(RightOUT, HIGH);
    LTstate = true; // Активируем таймер левого поворота
    RTstate = true; // Активируем таймер правого поворота
    ROnTime = millis(); // Переменная начала отсчтета таймера
    LOnTime = millis(); // Переменная начала отсчтета таймера
  }
  
// Таймер левого поворота  
  if(LTstate)  
    if (millis() - LOnTime > pause) {
    digitalWrite(LeftOUT, LOW);
    LTstate = false;
  }
  
// Таймер правого поворота
  if(RTstate) 
    if (millis() - ROnTime > pause) {
    digitalWrite(RightOUT, LOW);
    RTstate = false;
  }
}

 

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

CarismaGLX пишет:

Ну может еще помидорками покидаетесь! )))

 С помидорками напряг. Зима все же. Могу кинуть кирпич. #15

Конечно это не ваше решение, но где-то я только так могу.

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

Да в общем то с задержкой то я разобрался, даже больше чем надо и в каких тока "позах" ее можно делать, знаю уже минимум 3 способа, и этот скетч который я выложил рабочий, просто не получается реализовать разные команды на одних и тех же пинах, даже прерыванием! Тут фишка я так понял в физической невозможности, а не программной. Если сделать 3-й вход на "аварийку", то это добавит проблем, так как придется ее исключить из цепи автомобиля и запитать все напрямую, а на ней убрать фиксатор и сделать чисто однопозиционной кнопкой для 3-го канала!

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

qwone пишет:

Есль три кнопки : левый поворот , правый поворот и аварийка

И 4 состояния: ничего не мигает, правая мигает, левая мигает, правая и левая мигает.

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

nik182
Offline
Зарегистрирован: 04.05.2015

Зачем аварийку исключать из цепей автомобиля? На штатной аварийной кнопке есть контакт на который выдается 12 вольт при нажатии на кнопку. Возьмите с него сигнал через делитель 4.7к 7.5к.

CarismaGLX
CarismaGLX аватар
Offline
Зарегистрирован: 19.02.2013

qwone пишет:

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

Да сложилась уже картина, я настолько глубоко копал что не увидел перед своей мордой то, что я не оставил времени задержки для считывания информации с обоих входов, поэтому они друг друга и тушили, ибо нажать одновременно физически не реально, хватило задержки delay в 100 пока не считается состояние "Нажаты оба", а оно считывало либо левый, либо правый.... вот я дурак.... Спасибо кстати за идею с состояниями у меня их 3 вышло, левая, правая, обе!

nik182 пишет:

Зачем аварийку исключать из цепей автомобиля? На штатной аварийной кнопке есть контакт на который выдается 12 вольт при нажатии на кнопку. Возьмите с него сигнал через делитель 4.7к 7.5к.

Суть вот в чем, что есть "обратка" при включении кнопки "Аварийки" сигнал появиться и на проводах с подрулевого, тут либо диодами развязку делать придется, либо их надо было использовать вместе, что собственно у меня и получилось наконец таки!!! 

Осталось теперь еще одну "фишку" добавить, это убрать фиксатор кнопки, и сделать программную фиксацию при удержании, и функцию "Спасибо" при однократном нажатии, есть какой нить пример у Вас тут, я то я по интернету глянул там библиотеку целую тулить придется.....