Здравствуйте! Подскажите как добавить в код своего рода резервную активацию если кнопка не сработала по каким либо причинам. Каждое нажатие кнопки производит вкл и выкл 2 реле, но во время эксплуатации бывают механические сбои нажатия кнопок необходим участок кода который бы производил действие digitalWrite(10, LOW); digitalWrite(11, HIGH); если кнопка 2 не использовалась более 5 секунд и аналогично digitalWrite(10, HIGH); digitalWrite(11, LOW); если кнопка 3 не использовалась более 5 секунд. Таким образом хочу производить своего рода обнуление. Код (C++): #include <Servo.h> Servo servo1; void setup() { Serial.begin(9600); pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP); servo1.attach(5); pinMode(10, OUTPUT); digitalWrite(10, LOW); pinMode(11, OUTPUT); digitalWrite(11, LOW); } bool flag1 = false; bool flag2 = false; void loop() { servo1.write(random(10, 80)); //Serial.println("servo"); delay(1000); servo1.write(random(81, 150)); //Serial.println("SERVO"); delay(1000); } void yield() { bool btnState1 = !digitalRead(2); if (btnState1 && !flag1 ) { // обработчик нажатия flag1 = true; Serial.println("2"); digitalWrite(10, LOW); digitalWrite(11, HIGH); } if (!btnState1 && flag1) { // обработчик отпускания flag1 = false; } bool btnState2 = !digitalRead(3); if (btnState2 && !flag2 ) { // обработчик нажатия flag2 = true; Serial.println("3"); digitalWrite(10, HIGH); digitalWrite(11, LOW); } if (!btnState2 && flag2) { // обработчик отпускания flag2 = false; } }
Поставить таймер. А зачем тогда вообще кнопки, если можно каждые пять секунд команды подавать? Код (C++): void loop(){ static uint32_t timer = millis(); if(uint32_t(millis() - timer) > 5000) { timer = millis(); // ваш код }
Спасибо за ответ. Мне скорее не совсем таймер нужен, а резервный способ перезапуска цикла. Попытаюсь объяснить что из себя представляет проект. Реле запускает двигатель который, движет объект по прямой этот объект доходит то кнопки и ударяется об нее, и переключает реле в обратную сторону, и движется к другой кнопке и так по кругу. Кнопки необходимы, но они иногда дают сбой механического характера. Тем самым объект доходит до кнопки, ударяется об нее, но она не подает сигнал переключить реле, что бы объект начал движение в другую сторону. И вот мне нужен такой таймер который включался в тот момент когда происходит такой сбой. Я делал данный проект без кнопок просто задавая через delay движение в одну и другую сторону, но там присутствуют проблемы механического характера объяснять долго.
А если при нажатии на кнопку будет происходить "timer = millis()", сбрасывая таймер до его срабатывания? Если кнопка не сработает, то таймер сработает через заданное время.
не кнопки а концевики - делайте реверс по последнему срабатыванию что-то мешает сделать на индуктивном датчике - как нормально делают
Согласен. Нужен другой датчег. Ну а здесь можно сделать по условию ИЛИ. Если сработала кнопка ИЛИ прошло period то меняем направление движения и обнуляем period. Причем выбираем это время чуть больше чем нужно для движения из точки в точку. Каретка приходит и упирается и если кнопка не срабатывает то реверс включается по времени. Как то так
Да вы поняли в точку, что я хочу сделать вкл таймера после нажатия кнопки и если другая кнопка не заработала то по завершению таймера происходит действие. Это по сути внедрение в if mills(). Но у меня не получается это написать с точки зрения программирования. Я пробовал его добавить в if (btnState2 && !flag2 ) но не выходило. Не хватает знания С++.
Да концевики вы правы, но их у меня нет собираю, так сказать, из чего есть под рукой. Если бы были нормальные концевики тему не заводил.
Других датчиков нет. И да я так и представлял вписать mills в if, но не хватает знания в с++ что бы сделать это правильно.
Для начала, попробуйте вариант с защитой от дребезга контактов. Код (C++): #include <Servo.h> Servo servo1; #define DELAY 50 void setup() { Serial.begin(9600); pinMode(2, INPUT_PULLUP); pinMode(3, INPUT_PULLUP); servo1.attach(5); pinMode(10, OUTPUT); digitalWrite(10, LOW); pinMode(11, OUTPUT); digitalWrite(11, LOW); } bool flag1 = false; bool flag2 = false; void loop() { servo1.write(random(10, 80)); //Serial.println("servo"); delay(1000); servo1.write(random(81, 150)); //Serial.println("SERVO"); delay(1000); yield(); } void yield() { bool btnState1 = !digitalRead(2); if (btnState1 && !flag1 ) { // обработчик нажатия flag1 = true; Serial.println("2"); digitalWrite(10, LOW); digitalWrite(11, HIGH); delay(DELAY); } if (!btnState1 && flag1) { // обработчик отпускания flag1 = false; delay(DELAY); } bool btnState2 = !digitalRead(3); if (btnState2 && !flag2 ) { // обработчик нажатия flag2 = true; Serial.println("3"); digitalWrite(10, HIGH); digitalWrite(11, LOW); delay(DELAY); } if (!btnState2 && flag2) { // обработчик отпускания flag2 = false; delay(DELAY); } }
концевыми называют выключатели. Как правило, это аварийный элемент безопасности. вполне нормально посадить на таймер контроль срабатывания какого-то датчика. В АСУТП это применяется на каждом шагу.
Да согласен с вами. Вот только не знаю как это реализовать в виде кода. Пробовал вписывать в if (!btnState1 && flag1 || !btnState2 - mills() >= 5000). Пишу по памяти, но вроде так выглядело.
завести флаг (у меня это timer), отображающий срабатывание таймера (что означает, что таймер своё оттикал). И далее в коде: Код (C++): if (btn || timer) { // code here }
я пользуюсь вот такими обработчиками экземпляра таймера: Код (C++): static volatile SoftClock_t SoftTime_System = 0uL; void SoftTime_SysTick(uint8_t step_value) { SoftTime_System += step_value; } void SoftTimer_Disarm(SoftTimer_t* const SoftTimer) { SoftTimer->Start = 0; SoftTimer->End = 0; } void SoftTimer_ReSet(SoftTimer_t* const SoftTimer) { SoftTimer->Start = SoftTime_System; } void SoftTimer_Set(SoftTimer_t* const SoftTimer, const SoftClock_t SoftTime) { SoftTimer_ReSet(SoftTimer); SoftTimer->End = SoftTime; } Bool_t SoftTimer_FreeRun(SoftTimer_t* const SoftTimer, const SoftClock_t SoftTime) { Bool_t result = FALSE; if (SOFTTIMER_ARMED == SoftTimer_Status(SoftTimer)) { if (SOFTTIMER_ARMED == SoftTimer_Expired(SoftTimer)) { SoftTimer_Disarm(SoftTimer); result = TRUE; } } else { SoftTimer_Set(SoftTimer, SoftTime); } return result; } Bool_t SoftTimeDeadCheck(SoftClock_t ti, SoftClock_t td) { Bool_t result = FALSE; if ((SoftTime_System - ti) >= td) { result = TRUE; } return result; } Bool_t SoftTimer_Expired(SoftTimer_t* const SoftTimer) { Bool_t result = FALSE; if (SOFTTIMER_ARMED == SoftTimer_Status(SoftTimer)) { result = SoftTimeDeadCheck(SoftTimer->Start, SoftTimer->End); } return result; } Bool_t SoftTimer_Status(SoftTimer_t* const SoftTimer) { Bool_t result = FALSE; result = (SoftTimer->End != 0)? TRUE : FALSE; return result; } чтобы накинуть таймер, необходимо вызвать SoftTime_SysTick. Например, в прерывании аппаратного таймера или в любом другом месте. Ну а с остальным всё понятно.
Я имел в виду что-то типа такого. Можно попробовать удалить строки с комментарием "сброс таймера, если нужно". Код (C++): #include <Servo.h> Servo servo1; #define BUTTON1 2 #define BUTTON2 3 #define RELAY1 10 #define RELAY2 11 #define SERVO 5 #define DELAY 50 #define TIMER 5000 void setup() { Serial.begin(9600); pinMode(BUTTON1, INPUT_PULLUP); pinMode(BUTTON2, INPUT_PULLUP); servo1.attach(SERVO); pinMode(RELAY1, OUTPUT); digitalWrite(RELAY1, LOW); pinMode(RELAY2, OUTPUT); digitalWrite(RELAY2, LOW); } bool flag1 = false; bool flag2 = false; void loop() { servo1.write(random(10, 80)); //Serial.println("servo"); delay(1000); servo1.write(random(81, 150)); //Serial.println("SERVO"); delay(1000); yield(); } void button1() { digitalWrite(RELAY1, LOW); digitalWrite(RELAY2, HIGH); } void button2() { digitalWrite(RELAY1, HIGH); digitalWrite(RELAY2, LOW); } void yield() { // button 1 action static uint32_t timer1 = millis(); if (uint32_t(millis() - timer1) > TIMER) { timer1 = millis(); // сброс таймера, если нужно button1(); } bool btnState1 = !digitalRead(BUTTON1); if (btnState1 && !flag1 ) { // обработчик нажатия flag1 = true; Serial.println("BUTTON1"); timer1 = millis(); // сброс таймера button1(); delay(DELAY); } if (!btnState1 && flag1) { // обработчик отпускания flag1 = false; delay(DELAY); } // button 2 action static uint32_t timer2 = millis(); if (uint32_t(millis() - timer2) > TIMER) { timer2 = millis(); // сброс таймера, если нужно button2(); } bool btnState2 = !digitalRead(BUTTON2); if (btnState2 && !flag2 ) { // обработчик нажатия flag2 = true; Serial.println("BUTTON2"); timer2 = millis(); // сброс таймера button2(); delay(DELAY); } if (!btnState2 && flag2) { // обработчик отпускания flag2 = false; delay(DELAY); } }
Я так и делал не получилось. У меня не получалось сбросить его хоть я и писал timer = millis(); но видимо неверно.
Красивый код, но срабатывание по таймеру не действует, может я что-то не понял в нем конечно. Как я понял в этом участке и происходит работа таймера: staticuint32_t timer1 = millis(); if(uint32_t(millis()- timer1)> TIMER) { timer1 = millis();// сброс таймера, если нужно button1(); } Прошу прощения. Все заработало.