Всем привет. Начал разбираться с Ардуино и даже помигать светодиодом не смог... Помогите понять в чём проблема? Имеется: Ардуино Нано Atmega328P. Светодиод с резистором. 4х позиционный переключатель. Задача. Сделать 3 режима мигания светодиода. В каждом режиме должна настраиваться частота мигания часы/минуты/секунды. Физический переключатель переключает режимы ВЫКЛ /1 режим / 2 режим / 3 режим. Переключатель стоит между 12 пином и 3, 4, 5. Выключатель работает нормально, я его прозванивал. А проблема вот в чём. Подключаю всё на макетке, переключаю режимы, контролирую по монитору. Режимы отрабатывают нормально, переключатся и пишут забитое время, вроде всё ок. Но иногда, когда оставляешь всё в покое и ничего не трогаешь, начинается рандомная активация режимов. Например всё отключено, что подтверждает сообщение в мониторе порта и вдруг активируется 2ой режим, потом первый и секунд 10-15 остаётся активным. Выключатель из схемы вообще иногда вытаскивал, а ардуина всё равно переключала режимы сама. Потом вроде успокоится и всё опять работает нормально. А иногда вообще переключатель игнорит и сама режимы меняет - закономерность не смог понять и вообще почему это происходит. Хотел уже скетч с 0 переписать заново, но стало интересно, от чего такое происходит? Скетч. Код (C++): #define PINMODE_1 3 #define PINMODE_2 4 #define PINMODE_3 5 #define light 1000 long previousTimer = 0; void setup() { pinMode(2, OUTPUT); pinMode(PINMODE_1, INPUT); pinMode(PINMODE_2, INPUT); pinMode(PINMODE_3, INPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT); pinMode(12, OUTPUT); Serial.begin(9600); } void loop() { digitalWrite(12, HIGH); if (digitalRead(PINMODE_1)) // 1 режим работы { byte hour1 = 0; //Выставляем интервал режима 1 в часах. byte minute1 = 0; //Выставляем интервал режима 1 в минут. byte second1 = 1; //Выставляем интервал режима 1 в секундах. int mode_1 = hour1*(60000*2)+minute1*60000+second1*1000; unsigned long currentTimer = millis(); long interval = mode_1; if(currentTimer - previousTimer > interval) { previousTimer = currentTimer; digitalWrite(6, HIGH); delay(light); //Время отработки мигания. digitalWrite(6, LOW); } Serial.print("1 mode is chosen "); Serial.print(hour1); Serial.print(":"); Serial.print(minute1); Serial.print(":"); Serial.println(second1); delay(1000); } else if (digitalRead(PINMODE_2)) // 2 режим работы { byte hour2 = 0; //Выставляем интервал режима 2 в часах. byte minute2 = 0; //Выставляем интервал режима 2 в минут. byte second2 = 2; //Выставляем интервал режима 2 в секундах. int mode_2 = hour2*(60000*2)+minute2*60000+second2*1000; unsigned long currentTimer = millis(); long interval = mode_2; if(currentTimer - previousTimer > interval) { previousTimer = currentTimer; digitalWrite(7, HIGH); delay(light); //Время отработки мигания. digitalWrite(7, LOW); } Serial.print("2 mode is chosen "); Serial.print(hour2); Serial.print(":"); Serial.print(minute2); Serial.print(":"); Serial.println(second2); delay(1000); } else if (digitalRead(PINMODE_3)) // 3 режим работы { byte hour3 = 0; //Выставляем интервал режима 3 в часах. byte minute3 = 0; //Выставляем интервал режима 3 в минут. byte second3 = 3; //Выставляем интервал режима 3 в секундах. int mode_3 = hour3*(60000*2)+minute3*60000+second3*1000; unsigned long currentTimer = millis(); long interval = mode_3; if(currentTimer - previousTimer > interval) { previousTimer = currentTimer; digitalWrite(8, HIGH); delay(light); //Время отработки мигания. digitalWrite(8, LOW); } Serial.print("3 mode is chosen "); Serial.print(hour3); Serial.print(":"); Serial.print(minute3); Serial.print(":"); Serial.println(second3); delay(1000); } else { digitalWrite(2,LOW); Serial.println("OFF"); delay(1000); } } Прошу отнестись с пониманием если ерунду спрашиваю. С Ардуиной первый раз встречаюсь.
Висячие контакты помехи ловят. Их нужно подтянуть к питанию (режим INPUT_PULLUP) или резистором примерно на 40 - 50 кОм к 0. В первом случае замыкать на 0 и принимать LOW, во втором случае замыкать на Vcc и принимать HIGH
Все очень просто, неподключенные выводы висят в воздухе и как антенны ловят наводки, и Ардуина воспринимает их как сигналы. Что делать, ну во первых, освободить 12 пин и заменить его на плюс, а к 1, 2, и 3 подключить резисторы 10-20кОм и на землю. Таким образом, когда ничего не подключенно, на них будет минус (через резистор).
У вас входы D3-D5 включены без подтяжки, поэтому реагируют на наводки и помехи. Код (C++): pinMode(PINMODE_1, INPUT_PULLUP); //включаем подтяжку pinMode(PINMODE_2, INPUT_PULLUP); pinMode(PINMODE_3, INPUT_PULLUP); Вместо использования D12 контакт переключателя подключить к земле и считывать нулевой уровень Код (C++): if (!digitalRead(PINMODE_1))
Спасибо за ответы! Кстати в коде я вывод на 3 светодиода делал - это у же в процессе испытаний делал наглядную индикацию - без компа. Я пробовал резиторы к 0 прокидывать, но видимо слишком маленькие... Попробую Код (C++): pinMode(PINMODE_1, INPUT_PULLUP); //включаем подтяжку pinMode(PINMODE_2, INPUT_PULLUP); pinMode(PINMODE_3, INPUT_PULLUP); И позже 12й контакт я на + заменил уже =)
Потестил! Спасибо! Я в правильную сторону думал, но не до конца! Я пробовал INPUT_PULLUP, но подавал + на переключатель, а надо было "-"... И пробовал ставить резисторы между выводом и 0, а надо было к "+"... Резисторов нужных под рукой нет, сделал, как посоветовал ZAZ-965, вроде работает стабильно! Спасибо! Я читал, что подтягивающие резисторы лучше всё таки внешние использовать, позже, как прийдут заменю на внешние. Ещё раз спасибо!
С чего бы это? Меньше деталей, надёжнее схема. Только нужно учитывать, что разомкнутая кнопка дает уровень HIGH, и замыкать её надо на 0, и ловить LOW. Еще бывает на кнопку фильтр вешают. Но у вас логика скетча не чувствительна к дребезгу. Можно без обвязки обойтись.
Можно вклиниться. Поясните, плиз. Я для кнопок использовал библиотеку Bounce.h. Проверяю HIGH уровень. Код (C++): if ( bouncer1.read() == HIGH) Мне нужно изменить схему подключения кнопки и код? Цель - убрать ложные срабатывания. Благодарю.