Нужна помощь по остановке выполнения функции если начальное условие сменилось!
- Войдите на сайт для отправки комментариев
Втр, 13/12/2016 - 21:28
Всем привет! Помогите разобраться люди добрые, как сделать прерывание функций во время работы устройства. Принцип такой: "клацаем" левый поворотник без его фиксации, выполняется команда включения с задержкой на 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);
}
Ну так избавляйтесь от delay().
Вместо
delay (pause);
везде пишите
for (int i=0; i < pause; i++) { if (<УСЛОВИЕ ШУХЕРА>) return; delay(1); }Что там за "условие шухера" у Вас я не знаю, пропишете по какому именно условию нужно из функции срочно выпрыгивать.
andriano, я не так давно начал разбираться в программировании, обычно переделывал готовые скетчи или использовал библиотеки, а вот с таким за пол года впервые столкнулся... ибо никто такое устройство на ардуино не делал... поэтому решил попросить помощи ибо я уже с этим скетчем муздохаюсь вторые сутки, не выдержал! )
ЕвгенийП, спасибо, попробую переделать!
https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
andriano, читал я уже это и даже пробовал, я же не с фонаря решил тему создать, я сначала по гуглу прошелся форумы почитал, из того что мне нужно либо на чисто С написано либо на Ассемблере, а я в них полный ноль..... но всеравно спасибо.
ЕвгенийП, попробовал, переделал эффект тот же, пока функция не досчитает условие до нужного значения, к другой не переходит, как бы так объяснить.... в общем, есть два выключателя и две лампочки, нужно сделать так чтобы каждый выключатель включал свою лампочку, НО если при включении первого вторая лампочка горит, то ее гасить и наоборот.
Ошибка не в программе. Ошибка в самом алгоритме.
Есль три кнопки : левый поворот , правый поворот и аварийка
И 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; // "Обычный ход" }В работе код не проверял.
qwone, спасибо за наводку, суть уловил, буду пробовать, но завтра на свежую голову, ибо когда долго ковыряешься мозг отключается! )
Ардуино пока не отработает задержку в 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) { // Проверяем состояние, включен ли левый поворот 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); }Вот еще до скетча мой хрустальный шар показывал что ТС читал не пины а переменные...
Ну, правильно. Чего Вы написали то? Вот взять строки 43-47. Вы крутитесь в цикле до тех пор пока либо не закончится цикл, либо переменная LTState не станет равной 1. Скажите мне, каким образом она станет 1? Кто и когда её сделает 1 в этом цикле? Никто и никогда. Напишите нормальное условие и будет счастье.
Посмотрите и такой код дя общего развития
#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); } } }ЕвгенийП, так это же переменная получаемая при нажатии кнопки.... или я туплю совсем?
vosara, спасибо Вам попробую и этот, в любом случае при помощи или без помощи если разберусь отпишу здесь и выложу рабочий код, чтобы люди так же не мучались если будут искать!
ЕвгенийП, так это же переменная получаемая при нажатии кнопки.... или я туплю совсем?
Я не знаю, тупите Вы или нет. Я вам задал простой вопрос: "Скажите мне, каким образом она станет 1? Кто и когда её сделает 1 в этом цикле?" Так ответьте ж на него. Себе в первую очередь. Только без общих теорий, а точно и чётко: "Эта переменная станет 1 в строке № при таком-то условии".
А потом подумайте, а в тот момент, когда программа крутится в цикле, она может в эту саму строку № попасть?
Подумайте.
Почему то новички очень часто думают что переменные ВСЕГДА равны состоянию пинов. И не важно где они их приравняли. Нужно уже сделать такой тип данных pin который равен пину в реальном времени (или почти).
ЕвгенийП, Mr.Privet, ну что поделать товарищи, не все сразу стали гуру, я же не злюсь когда меня как электрика 4-го разряда спрашивают, а как подключить розетку, не правда ли тупой вопрос? Тут уж кто чем занимается, так что от этого не уйти.... А работа над ошибками проведется, спасибо за помощь!
ЕвгенийП, Mr.Privet, ну что поделать товарищи, не все сразу стали гуру...
Не стали, а некоторые не хотят и не чешатся. Но к вам это не относится, это я про других. Если продолжите разбираться с Ардуино через годик сами посмеетесь над своими постами. Вы поняли где у вас была ошибка? Давайте пробежимся: комментарии к коду в 10 посту: в строках 29, 30, 31 Вы правильно присваиваете переменным состояние пинов. У Вас кнопки "считываются" только там. Но в ифах вы уже работаете с переменными, то есть условия на вылет из цикла у Вас зависят от переменной, которая может измениться только в строках 29,30,31 грубо говоря переменная не обновляется. Если писать не
if (RTState == 1) return а if (digitalRead(RTSpin== 1)) return то будет Вам счастье. Ну или все это напрашивается на цыкл while{}. Как домашнее задание подумайте что будет если зажать две кнопки левого и правого поворота. Вообще данную задачу правильнее решать как сказал Винни Пух
Mr.Privet, именно код Винни я и взял в пример, а моя ошибка в том что я как Вы сказали думал что приоритет у команды считывания кнопки... так что вечерком, после работы покумекаю еще, как реализую "правильную" работу системы, скину код еще раз, может что-то оптимизировать получиться, ибо мне это все запихнуть в Тиньку13 надо, а там памяти с горошину! ))
В общем долго я "кумекал", перечитал кучу всего, собрал "франкинштейна", повороты работают как мне надо, за исключением того что не могу организовать одновременную работу левого и правого ("аварийку"), ибо они друг друга "тушат", есть ли возможность "подружить" обе стороны не в ущерб фунционалу? Ну может еще помидорками покидаетесь! )))
// Комфортные поворотники "Лентяйка" с фунцией "Спасибо" // Входы 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; } }Ну может еще помидорками покидаетесь! )))
С помидорками напряг. Зима все же. Могу кинуть кирпич. #15
Конечно это не ваше решение, но где-то я только так могу.
Да в общем то с задержкой то я разобрался, даже больше чем надо и в каких тока "позах" ее можно делать, знаю уже минимум 3 способа, и этот скетч который я выложил рабочий, просто не получается реализовать разные команды на одних и тех же пинах, даже прерыванием! Тут фишка я так понял в физической невозможности, а не программной. Если сделать 3-й вход на "аварийку", то это добавит проблем, так как придется ее исключить из цепи автомобиля и запитать все напрямую, а на ней убрать фиксатор и сделать чисто однопозиционной кнопкой для 3-го канала!
Есль три кнопки : левый поворот , правый поворот и аварийка
И 4 состояния: ничего не мигает, правая мигает, левая мигает, правая и левая мигает.
Если составите таблицу состояний кнопок и какие действия они должны делать, может программа и сложится.
Зачем аварийку исключать из цепей автомобиля? На штатной аварийной кнопке есть контакт на который выдается 12 вольт при нажатии на кнопку. Возьмите с него сигнал через делитель 4.7к 7.5к.
Если составите таблицу состояний кнопок и какие действия они должны делать, может программа и сложится.
Да сложилась уже картина, я настолько глубоко копал что не увидел перед своей мордой то, что я не оставил времени задержки для считывания информации с обоих входов, поэтому они друг друга и тушили, ибо нажать одновременно физически не реально, хватило задержки delay в 100 пока не считается состояние "Нажаты оба", а оно считывало либо левый, либо правый.... вот я дурак.... Спасибо кстати за идею с состояниями у меня их 3 вышло, левая, правая, обе!
Зачем аварийку исключать из цепей автомобиля? На штатной аварийной кнопке есть контакт на который выдается 12 вольт при нажатии на кнопку. Возьмите с него сигнал через делитель 4.7к 7.5к.
Суть вот в чем, что есть "обратка" при включении кнопки "Аварийки" сигнал появиться и на проводах с подрулевого, тут либо диодами развязку делать придется, либо их надо было использовать вместе, что собственно у меня и получилось наконец таки!!!
Осталось теперь еще одну "фишку" добавить, это убрать фиксатор кнопки, и сделать программную фиксацию при удержании, и функцию "Спасибо" при однократном нажатии, есть какой нить пример у Вас тут, я то я по интернету глянул там библиотеку целую тулить придется.....