прошу сильно не пинать, понимаю, что вопрос ламерский))) Есть двойной переключатель (каким нормальный люди свет включают). Хочу привязать его к ардуино. Схема в аттаче. S1, S2 - кнопки с фиксацией, резисторы по науке, подтяжка на землю. Получаю следующую картину. Пока S1 разомкнут, переключаю S2 - все замечательно. Но стоит замкнуть S1 и переключать S2, отрабатывает как бог пошлет. Соответственно наоборот тоже самое, пока S2 разомкнут можно щелкать S1, все работает, стоит S2 замкнуть и абзац. Что интересно, эта схема работает при классической обработке кнопки Код (C++): void CheckSwitch1() { State = digitalRead(Pin_D); if (sob > 0) { if (millis() - CurrentMillis > 100) { if (sob == 1 && State == HIGH && PreviosState != State) { PreviosState = State; //обработка нажатия } else if (sob == 2 && State == LOW && PreviosState != State) { PreviosState = State; //обработка нажатия } sob = 0; } } else { if (State == HIGH && PreviosState != State) { sob = 1; CurrentMillis = millis(); } else if (State == LOW && PreviosState != State) { sob = 2; CurrentMillis = millis(); } } } void loop(){ CheckSwitch1(); } Но я переделал скеч на работу по прерываниям, и получаю вот такую неприятность. Вот код работы по прерыванию Код (C++): #include "PinChangeInterrupt.h" setup(){ attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(Pin_D), CheckSwitch, CHANGE); } void CheckSwitch() { disablePinChangeInterrupt(digitalPinToPinChangeInterrupt(Pin_D)); State = digitalRead(Pin_D); if (State == HIGH && PreviosState != State) { PreviosState = State; //обработка нажатия } else if (State == LOW && PreviosState != State) { PreviosState = State; //обработка нажатия } enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(Pin_D)); } Что подскажете? Может использовать подтяжку к питанию? Видел схему с резистивным делителем напряжения, конечно вариант, но хотелось бы понять, почему такой вариант не работает. Заранее всем спасибо за ответы!
покажите скетч. и, по поводу схемы - кнопки лучше к пинам через резистор в несколько сот Ом подключить
такой же код для второй кнопки. В скетче они обрабатываются разными функциями. Меняется только пин и обработчик нажатия
Заметил закономерность, если одна кнопка замкнута, то при замыкании второй отрабатывается код обработчика первой кнопки, и наоборот. Такое впечатление, что прерывание отрабатывает, только не на той кнопки которую нажимают, а на той, которая уже замкнута
я использую библиотеку PinChangeInterrupt.h, она позволяет повесить прерывания на все пины. https://github.com/NicoHood/PinChangeInterrupt Что характерно, я повесил 2 звонковые кнопки на эти же пины, все отлично работает. Проблема именно с тем, что одна кнопка замкнута, и при замыкании второй срабатывает прерывание на первой, как будто на ней тоже меняется фронт
Прерывание на все пины D0-D7 одно и то же, когда оно срабатывает - библиотека определяет, какой из пинов замкнут на ноль. Поскольку одна кнопка у вас нажата всегда. то вторая кнопка вообще не обрабатывается. Чтобы эти кнопки работали независимо - подключите их на разные прерывания. И таких прерываний только три, хотя пинов много.
И, кстати, есть мнение, что тратить прерывания на кнопки - это расточительство, ибо приемлимая скорость реакции легко достигается и стандартными средствами...
это многое объясняет. спасибо! сейчас попробую. у меня высоконагруженный проект, в лупе крутится масса всего, включая обмен данными, хотелось разгрузить его, повесив все добро (кнопки, датчики и тд) на прерывания. Если есть другой вариант, с удовольствием рассмотрю
Весь код не получится))) примерно вот так Код (C++): #include "PinChangeInterrupt.h" #define BOARD1_D 9 //пин ардуино #define BOARD2_D 6 //пин ардуино #define BOARD3_D 5 //пин ардуино struct TBoard { Types Type_ID = TYPE_NO; SA SA_ID = SA_NO; byte Adress; byte Pin_D; byte Pin_A; struct TLink Link; struct TValues Values; Func Func_ID = FUNC_NO; byte PreviosState = 255; byte State = 255; byte sob = 0; unsigned long CurrentMillis; }; struct TBoard Board[3]; void setup() { Board[0].Pin_D = BOARD1_D; Board[1].Pin_D = BOARD2_D; Board[2].Pin_D = BOARD3_D; SetBoardButton(0); SetBoardButton(2); } void SetBoardButton(byte BoardNum) { //кнопка Board[BoardNum].SA_ID = SENSOR; Board[BoardNum].Adress = BoardNum; pinMode(Board[BoardNum].Pin_D, INPUT); switch (BoardNum) { case 0: detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D)); attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D), detect_button0, CHANGE); break; case 1: detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D)); attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D), detect_button1, CHANGE); break; case 2: detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D)); attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D), detect_button2, CHANGE); break; } } void detect_switch0() { CheckSwitch(0); } void detect_switch1() { CheckSwitch(1); } void detect_switch2() { CheckSwitch(2); } void CheckSwitch(byte BoardNum) { disablePinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D)); Board[BoardNum].State = byte(digitalRead(Board[BoardNum].Pin_D)); if (Board[BoardNum].State == HIGH && Board[BoardNum].PreviosState != Board[BoardNum].State) { Board[BoardNum].PreviosState = Board[BoardNum].State; SendBoardInfo(1, 0, BoardNum); if (Board[BoardNum].Link.Link_Type == 1) { CheckFunctions(BoardNum); } } else if (Board[BoardNum].State == LOW && Board[BoardNum].PreviosState != Board[BoardNum].State) { Board[BoardNum].PreviosState = Board[BoardNum].State; SendBoardInfo(1, 0, BoardNum); if (Board[BoardNum].Link.Link_Type == 1) { CheckFunctions(BoardNum); } } enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(Board[BoardNum].Pin_D)); }
какого-то откровенного криминала в этом куске кода я не нашел. Из соображений - операция digitalRead() довольно медленная и не вполне верно выполнять ее в прерывании, правильно было бы выставлять флаг об изменении и проверять сигнал на пине в основной программе. Из замечаний "не по делу" - код всех трех меток switch в SetBoardButton абсолютно идентичен, метки вполне можно было бы объединить. Да и сам switch там вообще не нужен, - в процедуре CheckSwitch обе ветки - "if" и "else if" содержат один и тот же код, вполне можно было бы обойтись одной. Кстати. то что у вас реакция на включение и на выключение кнопок одна и та же - это не ошибка, так задумано?
спасибо, учту он не идентичен, каждый ссылается на свою функцию-обработчик прерывания, ибо невозможно использование в прерывании функции с параметром. это наследие от предыдущих реинкарнаций, в последствии уберу. По существу, так и не ясно почему такая реакция. У меня есть одно объяснение, оно ламерское, но по моему выглядит так: при замкнутой одной кнопки, в момент замыкания второй происходит изменение потенциала на первой кнопке (электронщики сейчас меня бы закидали какахами)))), что в свою очередь отлавливает библиотека.
Да, действительно, просмотрел. Кстати, в приведенном коде функций detect_buttonX (x = 0,1,2) - нет, зато есть соответствующие функции detect_switchX - так и надо? Ну мне кажется. что это вряд ли... если у вас пины сконфигурированы на вход, токи там никакие и один на другой влиять не должен