// 2-2 브레이크 시스템 타이머 인터럽트 사용 + watch dog timer + dimming
// 3-5-0 서서히 밝아지고 어두워지게
// 100Hz, 100scale PWM
// 루프 주기는 2ms
// 4-1 버튼 입력 코드 구조 및 채터링 회피 적용
#include <avr/wdt.h>
#define break_switch (2)
#define accel_switch (3)
#define hazard_led (9)
#define break_led (10)
#define pwm_led (11) //adding pwm
#define ON HIGH
#define OFF LOW
bool run_once = false;
bool toggle1 = false;
uint16_t count1 = 0;
uint8_t pwm_val = 0; //pwm init_value
// dimming
uint8_t countISR = 0;
uint8_t count1to100 = 0;
uint8_t count_dimming = 0;
uint8_t duty = 0;
uint8_t seq_dimming = 0;
// key chattering
bool flag_btn_act = false;
bool flag_btn_0 = false;
bool flag_btn_1 = false;
uint8_t delay_btn_0 = 0;
uint8_t delay_btn_1 = 0;
uint8_t count_push_0 = 0;
uint8_t count_push_1 = 0;
void setup() {
// put your setup code here, to run once:
//set pins as outputs
Serial.begin(115200);
Serial.println("reset");
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT); // built in led pwm
pinMode(13, OUTPUT);
cli(); //stop interrupts
set_timer_10KHz();
sei(); //allow interrupts
wdt_enable(WDTO_15MS);
} // end setup
void loop() {
// put your main code here, to run repeatedly:
//do other things
wdt_reset();
if (run_once == true) { // 2ms 마다
run_once = false;
digitalWrite(13, HIGH);
// key chattering routine start
check_btn_0(); // 2번 키입력 확인
check_btn_1(); // 3번 키입력 확인
// key chattering routine end
// key action routine
if (flag_btn_act == true){
action_btn; // 키 동작
}
// start
// proc_dimming();
// end
digitalWrite(13, LOW);
}
analogWrite(pwm_led, pwm_val);
Serial.println(pwm_val);
}
ISR(TIMER1_COMPA_vect) { // 100us마다 10KHz x 20 = 2ms 마다
if (countISR++ >= 19) {
countISR = 0;
run_once = true;
}
if (count1to100++ == 100) count1to100 = 1;
if (count1to100 > duty) digitalWrite(11, LOW);
else digitalWrite(11, HIGH);
}
void set_timer_1KHz() {
//set timer1 interrupt at 1KHz
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; //initialize counter value to 0
// set compare match register for 1KHz increments
OCR1A = 249; // = (16*10^6) / (1000*64) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 and CS10 bits for 64 prescaler
TCCR1B |= (1 << CS11) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
void set_timer_10KHz() {
//set timer1 interrupt at 10KHz
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; //initialize counter value to 0
// set compare match register for 10KHz increments
OCR1A = 199; // = (16*10^6) / (10000*8) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 and CS10 bits for 8 prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
void proc_dimming(void) {
if (count_dimming++ >= 9) {
count_dimming = 0;
switch (seq_dimming) {
case 0:
if (duty++ >= 100) seq_dimming = 1;
break;
case 1:
if (--duty == 0) seq_dimming = 0;
break;
}
}
}
// 1. CHECK-BTN 함수를 타이머 인터럽트에서 처리
// 2. PWM 출력을 LOOP내에서 처리
// 연속 키입력 처리
// 키매트릭스 처리
void check_btn_0(void) {
if (digitalRead(2) == HIGH) { // 버튼 누름
if (delay_btn_0++ >= 20) { // 2ms 마다 증가해서 누른채로 40ms지나면
if (flag_btn_0 == false) {
flag_btn_0 = true;
flag_btn_act = true;
count_push_0++;
Serial.println("count_push_0: " + String(count_push_0));
if(pwm_val != 255){
pwm_val++;
}
}
}
} else // 버튼 놓음, 또는 채터링시에도 변수 리셋
{
delay_btn_0 = 0;
flag_btn_0 = false;
}
}
void check_btn_1(void) {
if (digitalRead(3) == HIGH) { // 버튼 누름
if (delay_btn_1++ >= 20) { // 2ms 마다 증가해서 누른채로 40ms지나면
if (flag_btn_1 == false) {
flag_btn_1 = true;
flag_btn_act = true;
count_push_1++;
Serial.println("count_push_1: " + String(count_push_1));
if(pwm_val != 0) {
pwm_val--;
}
}
}
} else // 버튼 놓음, 또는 채터링시에도 변수 리셋
{
delay_btn_1 = 0;
flag_btn_1 = false;
}
}
void action_btn(void) {
if (flag_btn_0 == HIGH) { // break btn 버튼 누름
digitalWrite(break_led, HIGH);
if (count1 == 0) {
if (toggle1 == false) {
digitalWrite(hazard_led, HIGH);
} else {
digitalWrite(hazard_led, LOW);
}
}
if (++count1 >= 2000) { // 1ms X 2000 = 2초
count1 = 0;
toggle1 = !toggle1;
}
}
if ((flag_btn_1 == ON) && (flag_btn_0 == OFF)) {
count1 = 0;
toggle1 = false;
digitalWrite(break_led, LOW);
digitalWrite(hazard_led, LOW);
}
flag_btn_act == false;
}