Управление реле

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

DooDllez пишет:

 

Если визуально не понятно чего хочу добиться на примере колеса. То представьте как работают дворники на авто. Есть 3 режима: прерывистый, постоянный и быстрый. Где бы вы не отключили дворники они вернутся в изначальное положение. Ровно то-же самое.

 

Ваша задача это типичная State Machine. Ну или "конечный автомат" если по-русски, но звучит коряво.

Вот например - https://habr.com/ru/post/345960/

-NMi-
Offline
Зарегистрирован: 20.08.2018

DooDllez пишет:

Я электрик.

Ну раз ты електрег, то просто обязан знать, что такое десятичный счётчик и диодное ИЛИ! ТвоЙа "задачка" решАема за один час на макетке! И, если уж, нет у тебя заплатить людям за скетч  ---  иди сходи, поставь пару электрических розеток в дом 2 х $50 = $100  , какрас, как Дет прасил. Или павесь люстру, или щиток сабери, один х.ер $100   !!!

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

Если переключили на режим 1 или 2 а концевик в сработавшем положении что делаем ? Сразу включаем реле или ждём пока концевик отпустит? И что в этом случае с паузой 5 сек ? 

DooDllez
Offline
Зарегистрирован: 04.10.2018

nik182 пишет:

Если переключили на режим 1 или 2 а концевик в сработавшем положении что делаем ? Сразу включаем реле или ждём пока концевик отпустит? И что в этом случае с паузой 5 сек ? 

Когда мы включаем любой режим то реле срабатывает сразу. Т.к наше колесо стоит в нейтральном положении а значит концевик замкнут. 

Мы обращаемся к концевику только в тот момент когда выключаем режим, что-бы реле было замкнутым до того момента пока колесо не вернется в нейтральное положение. 

И в 1й функции когда идет оборот пауза оборот пауза.

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

режимы 4-5-6 сами по себе, никак не относятся к 1-2-3

DooDllez
Offline
Зарегистрирован: 04.10.2018

Запустил 4-5 функцию. Только после включения самого ардуино, она замыкает реле. Но если включаю и отключаю функцию реле остается разомкнутым как и должно быть. Не пойму де поправить чтоб ардуино его не включала изначально...

const int PIN_BUTTON = 4;
const int PIN_REL = 11;

void setup() {
  Serial.begin(9600);
  pinMode(PIN_REL, OUTPUT);
}

void loop() {
  int buttonState = digitalRead(PIN_BUTTON);
  Serial.println(buttonState);
  if (!buttonState) {
    delay(50);
    return;
  }

  digitalWrite(PIN_REL, LOW);
  delay(1000);
  digitalWrite(PIN_REL, HIGH);
  delay(1000);
}

 

DooDllez
Offline
Зарегистрирован: 04.10.2018

Вроде разобрался. Не знаю правильно ли это.

Добавил в setup 

digitalWrite(PIN_RELAY, HIGH);

DooDllez
Offline
Зарегистрирован: 04.10.2018

Получилось что 4-5-6 кнопка работают. Но по одной логике. Нужно привязать кнопку к определенному действию, но не понимаю как это сделать. Чтоб 4 запускала rel9, 5 запускала rel10, а 6 запускала вместе rel9 и rel10.

const int PIN_BUTTON4 = 4;
const int PIN_BUTTON5 = 5;
const int PIN_BUTTON6 = 6;
const int PIN_REL9 = 9;
const int PIN_REL10 = 10;

void setup() {
  Serial.begin(9600);
  pinMode(PIN_REL9, OUTPUT);
  pinMode(PIN_REL10, OUTPUT);
  digitalWrite(PIN_REL9, HIGH);
  digitalWrite(PIN_REL10, HIGH);

}

void loop() {
  int buttonState = digitalRead(PIN_BUTTON4);
  Serial.println(buttonState);
  if (!buttonState) {
  int buttonState = digitalRead(PIN_BUTTON5);
  Serial.println(buttonState);
  if (!buttonState) {
  int buttonState = digitalRead(PIN_BUTTON6);
  Serial.println(buttonState);
  if (!buttonState) {
    return;
      }
    }
  }

  digitalWrite(PIN_REL9, LOW);
  delay(1000);
  digitalWrite(PIN_REL9, HIGH);
  delay(1000);
  digitalWrite(PIN_REL10, LOW);
  delay(1000);
  digitalWrite(PIN_REL10, HIGH);
  delay(1000);
}

Или я вообще все делаю не так?

astwo
Offline
Зарегистрирован: 10.07.2019

Попробую объяснить в терминах электриков. Вы сидите на форуме. И появляется тема собрать и подключить некое устройство. Вы рисуете схему и всплывает нюанс. Электрик то заказчик, но на уровне розеточника и схема нужна только на уровне подключения розетки. Но ведь схема устройства уже не розетка. Проводов побольше и уже он может накосячить с подключением и главное хрен увидит. Так и здесь раз нужна программа, то я не программист забудьте. И да знать надо как написать конечный автомат и разумеется для каждого алгоритма реле. И да копипаст не пройдёт. Маловато в инете таких программ. Те программы от дилетантов.

Green
Offline
Зарегистрирован: 01.10.2015

Пишите htpicc@gmail.com, отвлекусь.

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

В описании событий есть непонятные моменты. Например кнопку 1 нельзя просто отпустить. Ее можно только переключить в положение 2. Но есть два противоречивых требования - сразу должен начать работать режим 2 и реле должно оставаться включенным до появления минуса на концевике и тикает 5 секунд. Что делать? А если из режима 2 в режим 1 или 3?   

Пока получается как то так, но надо полировать момент переключения кнопок.

const int buttonE1 = 2;
const int buttonK1 = 3;
const int buttonK2 = 4;
const int buttonK3 = 5;
const int buttonK4 = 6;
const int buttonK5 = 7;
const int buttonK6 = 8;
const int rPin1 =  9;
const int rPin2 =  10;
const int rPin3 =  11;
const int rPin4 =  12;

byte flE1,flK1,flK2,flK3,flK4,flK5, flK6,fl5S;
unsigned long tR1, tR3, tR4, otR1, otR3, otR4;

void setup() {
  pinMode(rPin1, OUTPUT);
  pinMode(rPin2, OUTPUT);
  pinMode(rPin3, OUTPUT);
  pinMode(rPin4, OUTPUT);
  fl5S=0;
}

void loop() {
  
  if (digitalRead(buttonE1) == LOW)  flE1 = 1; 
  else flE1 = 0;
  if (digitalRead(buttonK1) == LOW) { flK1 = 1; flK2 = 0; } 
  else flK1 = 0;
  if (digitalRead(buttonK2) == LOW) { otR1 = millis();flK1 = 0; flK3 = 0; digitalWrite(rPin1, LOW);} 
  else if (flK3==1) if (flE1 == 0) digitalWrite(rPin1, LOW);   
  if (digitalRead(buttonK3) == LOW) { flK3 = 1; flK2 = 0; digitalWrite(rPin2, LOW);} 
  else {if ((flK3 == 1) && (flE1 == 0)) { flK3 = 0; digitalWrite(rPin2, HIGH);};};
  if (digitalRead(buttonK4) == LOW) { if (flK4 == 0) otR3 = millis(); flK4 = 1;} 
  else flK4 = 0;
  if (digitalRead(buttonK5) == LOW) { if (flK5 == 0) otR4 = millis(); flK5 = 1;} 
  else flK5 = 0;
  if (digitalRead(buttonK6) == LOW) { if (flK4 == 0) otR3 = millis(); if (flK5 == 0) otR4 = millis(); flK4 = 1;  flK5 = 1; } 
  else { if (digitalRead(buttonK4) == HIGH) flK4 = 0; if (digitalRead(buttonK5) == HIGH) flK5 = 0;
  };

  if (flK1 == 1) {
    if ((flE1==0)&&(fl5S==0)) {fl5S=1; otR1=millis();}; 
    if (fl5S==1){ 
       if ((millis() - otR1) < 5000) digitalWrite(rPin1, LOW);
       else  {digitalWrite(rPin1, HIGH); fl5S=0;};
    };
  };

  if (flK4 == 1) {
    tR3 = ((millis() - otR3) / 1000) % 2;
    if (tR3 == 0) digitalWrite(rPin3, LOW);

    else  digitalWrite(rPin3, HIGH);
  };
  if (flK5 == 1) {
    tR4 = ((millis() - otR3) / 1000) % 2;
    if (tR4 == 0) digitalWrite(rPin4, LOW);
    else  digitalWrite(rPin4, HIGH);
  };

}

 

DooDllez
Offline
Зарегистрирован: 04.10.2018

nik182 пишет:

В описании событий есть непонятные моменты. Например кнопку 1 нельзя просто отпустить. Ее можно только переключить в положение 2. Но есть два противоречивых требования - сразу должен начать работать режим 2 и реле должно оставаться включенным до появления минуса на концевике и тикает 5 секунд. Что делать? А если из режима 2 в режим 1 или 3?   

Пока получается как то так, но надо полировать момент переключения кнопок.

ОГО! ОГРОМНОЕ Вам спасибо что решили помочь. Сегодня не смогу протестировать правда, только завтра.

Кнопку 1 отключить можно. У переключателя есть положение в котором не идет никакой сигнал. В него можно попасть только через 1 режим.

Если задать условия что каждый режим из 1-2-3 отменяет действие предыдущего это вроде решает проблему переключений.

Если я верно понимаю то прописав отмену режимов друг друга, а выключение идет в любом случае через режим 1. Перед отключением включается режим 1 и потом сигнал пропадает, по заданному условию реле включено до поступления сигнала от концевика потом ждет 5 сек и не запускается снова т.к. нет никакого сигнала на 1-2-3 и в этом случае программу ничего не отменяет а новая команда на запуск не поступает. 

 

Green
Offline
Зарегистрирован: 01.10.2015

Вы не верили что с ТЗ нужно заниматься 2 дня (#11)? Так уже больше прошло, а люди до сих пор не разобрались.(

Гриша
Offline
Зарегистрирован: 27.04.2014

Green пишет:

Вы не верили что с ТЗ нужно заниматься 2 дня (#11)? 

Это кто это не верил? ну разве что в то, что вы оптимист!!! утрясти ТЗ за 2 дня :))))))))))))))))

UPD по грамотно составленному ТЗ продвинутым инженером, частенько  менее опытным спецам остается руку приложить без участия бОльшей половины серого вещества, коего у младшего состава спецов бывает скромное количество. Вот только таких грамотеев, которые смогут  расписать ТЗ на все случаи жизни я не встречал...

Green
Offline
Зарегистрирован: 01.10.2015

)) Бывает что уже сам распишешь как видится, ну только подтверди. Так нет же ж, в ответ опять простынь с обширным расписанием работы. И это описание опять нужно перечитывать, вникать, находить отличия от своего, отмечать противоречия и т.п. И так по несколько раз. Пока уже не психонёшь, да ответь ты по пунктам ДА или НЕТ, а если нет то что не так.(

Гриша
Offline
Зарегистрирован: 27.04.2014

Green пишет:

)) Бывает что уже сам распишешь как видится, ну только подтверди. Так нет же ж, в ответ опять простынь с обширным расписанием работы. И это описание опять нужно перечитывать, вникать, находить отличия от своего, отмечать противоречия и т.п. И так по несколько раз. Пока уже не психонёшь, да ответь ты по пунктам ДА или НЕТ, а если нет то что не так.(

писал ТЗ, дал товарищам проверить его - вроде все понятно и ничего не заметили... получили ПО "*@&% мать" мы даже представить не могли, что можно ТАК интерпретировать... 

Green
Offline
Зарегистрирован: 01.10.2015

Это называется "мы по разному видим мир".) Ну не в такой же степени!)))

astwo
Offline
Зарегистрирован: 10.07.2019

Скорее просто на разных языках писали. Вы привыкли писать по русски, а вам реализацию тз написали на китайском или индийском. Да ещё на отвяжись.

DooDllez
Offline
Зарегистрирован: 04.10.2018

nik182 пишет:

Пока получается как то так, но надо полировать момент переключения кнопок.

А у меня не работает  :(

Включаю ардуину, активируются сразу 4 реле из которых 2 щелкают. Как-бы функция 6 запущена.

 

Green пишет:

Вы не верили что с ТЗ нужно заниматься 2 дня (#11)? Так уже больше прошло, а люди до сих пор не разобрались.(

Ну я очень старался и схематично и на различных примерах объяснить принцип работы.

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

Поставте в 41 строку serialprint и выведите значения флагов flK1 - flK6, flE1 они длжны быть равны нулю пока кнопки не нажаты. Если это не так ищите почему. В сетапе перед инициализацией портов запишите в них единицы, что бы реле не щелкали при старте ардуины.

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

A там, в setup, не утеряны INPUT_PULLUP нигде?

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

Если резисторов у кнопок на +5 нет , то да, утеряны. Но у ТС было в ТЗ минус на ногу. Как это понимать не знаю.

DooDllez
Offline
Зарегистрирован: 04.10.2018

nik182 пишет:
Поставте в 41 строку serialprint и выведите значения флагов flK1 - flK6, flE1 они длжны быть равны нулю пока кнопки не нажаты. Если это не так ищите почему. В сетапе перед инициализацией портов запишите в них единицы, что бы реле не щелкали при старте ардуины.

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

nik182 пишет:

Если резисторов у кнопок на +5 нет , то да, утеряны. Но у ТС было в ТЗ минус на ногу. Как это понимать не знаю.

Минус на ногу - у кнопок тот-же минус что и у ардуино, при нажатии на кнопку этот минус попадает на входы ардуино.

В теории резистор можно добавить на вход кнопок.

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

Инициализируйте ноги кнопок в сетапе с квалификатором INPUT_PULLUP. Но если все это будет стоять на установке с мощными моторами то их явно не хватит. Особенно на коцевик. Нужно входные ноги соединить с плюсом 5 вольт резисторами 1к. Вот где паять придётся.

DooDllez
Offline
Зарегистрирован: 04.10.2018

nik182 пишет:

Инициализируйте ноги кнопок в сетапе с квалификатором INPUT_PULLUP. Но если все это будет стоять на установке с мощными моторами то их явно не хватит. Особенно на коцевик. Нужно входные ноги соединить с плюсом 5 вольт резисторами 1к. Вот где паять придётся.

Спасибо большое. Паять то не проблема, скорее всего так и сделаю через резистор.

Но сначала надо победить Serial.print 

astwo
Offline
Зарегистрирован: 10.07.2019

DooDllez пишет:

Смотрю на ваш прекрасный код и понимаю что я в нем ничего не понимаю :)


Вот по этому вы и не наблюдает очередей помогать вас. И как сказано в начале стоит будет не работа написать вам код, а научить вас понимать этот код ;)

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

Код написан в стиле индийских програмистов прямо, без разных чудес, с флагами, которые взводятся по нажатию кнопок или концевиков и в зависимости от комбинации флагов совершаются разные действия, без блокировки основного цикла через delay. Это первая прикидка, которую нужно отлаживать на реальном устройстве. Как я уже писал есть вопросы по перключению режимов и реакции программы на них. К сожалению в ближайшие две недели я буду в отрыве от цивилизации и смогу лишь только давать советы.

DooDllez
Offline
Зарегистрирован: 04.10.2018

astwo пишет:
DooDllez пишет:

Смотрю на ваш прекрасный код и понимаю что я в нем ничего не понимаю :)

Вот по этому вы и не наблюдает очередей помогать вас. И как сказано в начале стоит будет не работа написать вам код, а научить вас понимать этот код ;)

Я честно и не ожидал очередей. Темболее не ожидал такой помощи как оказывает nik182. Чем больше я пытаюсь понять его код, тем больше запутываюсь. Он написан далеко не на моем "деревянном" уровне. Мне его очень сложно понять и темболее дополнить. Все эти переменные и инвертирование которые здесь использованы не могу уловить.

Битый час пытаюсь внедрить сюда Serial.print и назначить кнопкам "нулевые позиции", но ничего не выходит. Как вношу изменения, все рушится или не функциклирует. И наверно в скором будущем у меня ничего и не выйдет. Да и было-бы странно если-бы вышло с таким профессиональным кодом.

Я не халявщик и буду даже рад оплатить рабочий код этому человеку, если он согласится доделать его для меня. Но к сожалению у меня нет возможности предложить большие цифры. Как писали выше "поставь пару розеток вот тебе и 100$", в моих реалиях далеко такого нет.

Ув. nik182 отпишете свой емаил или другое средство связи, может вас заинтересует мое предложение. Мне будет очень жаль если я не смогу доделать ваш код и он пропадет в пустую.

 

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

Вставил комментарии и добавил вывод и инициализацию. Деньги только за законченное и отлаженное устройство. Это не Ваш случай. 

const int buttonE1 = 2;
const int buttonK1 = 3;
const int buttonK2 = 4;
const int buttonK3 = 5;
const int buttonK4 = 6;
const int buttonK5 = 7;
const int buttonK6 = 8;
const int rPin1 =  9;
const int rPin2 =  10;
const int rPin3 =  11;
const int rPin4 =  12;

byte flE1,flK1,flK2,flK3,flK4,flK5, flK6,fl5S,flPr ; // флаги для кнопок и концевика
unsigned long tR1, tR3, tR4, otR1, otR3, otR4; // переменные для работы с millis 

void setup() {
  
  pinMode(buttonE1,INPUT_PULLUP); //кнопки и концевик с подтяжкой к +5
  pinMode(buttonK1,INPUT_PULLUP);
  pinMode(buttonK2,INPUT_PULLUP);
  pinMode(buttonK3,INPUT_PULLUP);
  pinMode(buttonK4,INPUT_PULLUP);
  pinMode(buttonK5,INPUT_PULLUP);
  pinMode(buttonK6,INPUT_PULLUP);

  digitalWrite(rPin1, HIGH);
  digitalWrite(rPin2, HIGH);
  digitalWrite(rPin3, HIGH);
  digitalWrite(rPin4, HIGH);
  
  pinMode(rPin1, OUTPUT);
  pinMode(rPin2, OUTPUT);
  pinMode(rPin3, OUTPUT);
  pinMode(rPin4, OUTPUT);
 
  fl5S=0; // флаг 5 секунд обнуляем

  Serial.begin(9600);
}

void loop() {
  
  if (digitalRead(buttonE1) == LOW)  flE1 = 1; // установка флага концевика.
  else flE1 = 0;
  if (digitalRead(buttonK1) == LOW) { flK1 = 1; flK2 = 0; if (flE1==1) digitalWrite(rPin1, LOW);  } // установка флага первой кнопки и если переключили из второго положения то его обнулить.Если не концевик включить реле1 
  else flK1 = 0; // сброс флага первой кнопки.
  if (digitalRead(buttonK2) == LOW) { otR1 = millis();flK1 = 0; digitalWrite(rPin1, LOW);} // сброс флага первой кнопки. Включение реле 1
  else if (flK3==1) if (flE1 == 1) digitalWrite(rPin1, HIGH); // если переключили в 3 режим то ждем концевик и отключаем реле 1   
  if (digitalRead(buttonK3) == LOW) { flK3 = 1; flK2 = 0; digitalWrite(rPin2, LOW);} // установка флага третьего режима. Включаем реле 2
  else {if ((flK3 == 1) && (flE1 == 1)) { flK3 = 0; digitalWrite(rPin2, HIGH);};}; // Если отключен третий режим то ждем концевика и оключaем реле и обнуляем флаг 3
  if (digitalRead(buttonK4) == LOW) { if (flK4 == 0) otR3 = millis(); flK4 = 1;} // если нажали кнопку 4 то запоминаем один раз время нажатия и ставим флаг 4
  else flK4 = 0; //кнопка 4 отпущена - обнуляем флаг
  if (digitalRead(buttonK5) == LOW) { if (flK5 == 0) otR4 = millis(); flK5 = 1;} 
  else flK5 = 0;
  if (digitalRead(buttonK6) == LOW) { if (flK4 == 0) otR3 = millis(); if (flK5 == 0) otR4 = millis(); flK4 = 1;  flK5 = 1; } // если кнопки 4 или 5 не нажаты то запоминаем время и взводим флаги
  else { if (digitalRead(buttonK4) == HIGH) flK4 = 0; if (digitalRead(buttonK5) == HIGH) flK5 = 0; // если кнопки 4,5,6 не нажаты то обнуляем флаги
  };

  if (flK1 == 1) { // если кнопка 1 нажата 
    if ((flE1==1)&&(fl5S==0)) {fl5S=1; otR1=millis();}; // если концевик сработал и не был запущен отсчет 5 секунд то запоминaем время и взводим флаг 5 секунд 
    if (fl5S==1){ // если запущен отсчет 5 секунд 
       if ((millis() - otR1) < 5000) digitalWrite(rPin1, HIGH); // пока не прошло 5 сек выключаем реле 
       else  {digitalWrite(rPin1, LOW); fl5S=0;}; // прошло 5 секунд включаем реле
    };
  };

  if (flK4 == 1) { //если нажата кнопка 4 или 6
    tR3 = ((millis() - otR3) / 1000) % 2; // посчитать четная или нечетная секунда
    if (tR3 == 0) digitalWrite(rPin3, LOW); // если четная включаем реле
    else  digitalWrite(rPin3, HIGH);       // если нечетная выключаем реле
  };
 
  if (flK5 == 1) { //если нажата кнопка 5 или 6
    tR4 = ((millis() - otR3) / 1000) % 2;
    if (tR4 == 0) digitalWrite(rPin4, LOW);
    else  digitalWrite(rPin4, HIGH);
  };

 if (((millis()/500) % 2) == 0) { // 1 раз в секунду вывести флаги 
  if (flPr==0) {
  Serial.print(flE1);
  Serial.print(" , ");
  Serial.print(flK1);
  Serial.print(" , ");
  Serial.print(flK2);
  Serial.print(" , ");
  Serial.print(flK3);
  Serial.print(" , ");
  Serial.print(flK4);
  Serial.print(" , ");
  Serial.print(flK5);
  Serial.print(" , ");
  Serial.println(flK6);
  flPr=1;
 };  
 }
 else flPr=0;
}