// Неправильно раб д3. Обработка от дребезга
const int pinD2 = 2; // Вход D2
const int pinD3 = 3; // Вход D3
const int ledPin = 13; // Светодиод на пине 13
const int pwmPin = 9; // Пин для ШИМ сигнала
const int potPin = A0; // Пин для потенциометра
volatile bool startPWM = false; // Флаг для управления ШИМ
volatile bool startTimer = false; // Флаг для управления таймером светодиода
volatile bool debounceFlag = false; // Флаг для фильтрации дребезга
volatile unsigned long debounceTime = 0; // Время последнего изменения состояния для дребезга
unsigned long lastPwmToggle; // Время последнего переключения состояния ШИМ
bool pwmState = false; // Текущее состояние ШИМ (включен/выключен)
unsigned long kofemolka_vremja; // Время работы светодиода
const unsigned long debounceDelay = 50; // Задержка для фильтрации дребезга (50 мс)
void setup() {
Serial.begin(9600); // Инициализация последовательного порта
Serial.println("Начало работы");
// Настраиваем пины с подтяжкой к плюсу
pinMode(pinD2, INPUT_PULLUP);
pinMode(pinD3, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
pinMode(pwmPin, OUTPUT);
// Настраиваем прерывания на пинах D2 и D3
attachInterrupt(digitalPinToInterrupt(pinD2), onD2Fall, FALLING); // Прерывание при спаде на D2
attachInterrupt(digitalPinToInterrupt(pinD3), onD3Change, CHANGE); // Прерывание при изменении состояния на D3
// Настраиваем Timer1 для прерываний
TCCR1A = 0; // Устанавливаем регистры в 0
TCCR1B = 0;
TCCR1B |= (1 << WGM12); // Включение в CTC режим
TCCR1B |= (1 << CS10) | (1 << CS12); // Установка битов CS10 и CS12 на коэффициент деления 1024
TIMSK1 |= (1 << OCIE1A); // Разрешаем прерывание по совпадению
// Настраиваем Timer2 для фильтрации дребезга
TCCR2A = 0; // Устанавливаем регистры в 0
TCCR2B = 0;
TCCR2B |= (1 << WGM21); // Включение в CTC режим
OCR2A = 249; // Установка периода таймера (1 мс при делении на 64)
TCCR2B |= (1 << CS22); // Установка битов CS22 на коэффициент деления 64
TIMSK2 |= (1 << OCIE2A); // Разрешаем прерывание по совпадению
}
void loop() {
// Считываем значение потенциометра и определяем время работы светодиода
kofemolka_vremja = map(analogRead(potPin), 0, 1023, 1000, 10000); // От 1 до 10 секунд
OCR1A = (kofemolka_vremja * 16) - 1; // Установка периода таймера для светодиода
// Обработка флага дебаунсинга
if (debounceFlag && (millis() - debounceTime) > debounceDelay) {
if (digitalRead(pinD2) == LOW) {
digitalWrite(ledPin, HIGH); // Включаем светодиод
startTimer = true;
TCNT1 = 0; // Сбросить счетчик таймера
TCCR1B |= (1 << CS10) | (1 << CS12); // Запуск таймера с делением 1024
Serial.println("D2 спад, запуск таймера");
}
debounceFlag = false; // Сбросить флаг дебаунсинга
}
// Обработка ШИМ
if (startPWM) {
if (millis() - lastPwmToggle >= 500) { // 500 мс для 2 Гц
pwmState = !pwmState;
analogWrite(pwmPin, pwmState ? 127 : 0); // Устанавливаем ШИМ на 50%
lastPwmToggle = millis();
Serial.println("ШИМ состояние изменено");
}
} else {
analogWrite(pwmPin, 0); // Выключаем ШИМ, если startPWM равен false
}
}
// Обработчик прерывания при спаде на D2
void onD2Fall() {
debounceFlag = true; // Устанавливаем флаг дебаунсинга
debounceTime = millis(); // Сохраняем время изменения состояния
TCCR2B |= (1 << CS22); // Запуск таймера для фильтрации дребезга
}
// Обработчик прерывания при изменении состояния на D3
void onD3Change() {
if (digitalRead(pinD3) == HIGH) {
startPWM = true; // Запуск ШИМ
Serial.println("D3 высокий, запуск ШИМ");
} else {
startPWM = false; // Отключение ШИМ
Serial.println("D3 низкий, отключение ШИМ");
}
}
// Обработчик прерывания Timer1 (управление светодиодом)
ISR(TIMER1_COMPA_vect) {
if (startTimer) {
digitalWrite(ledPin, LOW); // Отключаем светодиод
startTimer = false;
TCCR1B &= ~((1 << CS10) | (1 << CS12)); // Остановить таймер
Serial.println("Таймер завершился, отключение светодиода");
}
}
// Обработчик прерывания Timer2 (фильтрация дребезга)
ISR(TIMER2_COMPA_vect) {
if (debounceFlag && (millis() - debounceTime) > debounceDelay) {
if (digitalRead(pinD2) == LOW) {
digitalWrite(ledPin, HIGH); // Включаем светодиод
startTimer = true;
TCNT1 = 0; // Сбросить счетчик таймера
TCCR1B |= (1 << CS10) | (1 << CS12); // Запуск таймера с делением 1024
Serial.println("D2 спад, запуск таймера");
}
debounceFlag = false; // Сбросить флаг дебаунсинга
TCCR2B &= ~(1 << CS22); // Остановить таймер для фильтрации дребезга
}
}