본문 바로가기

아두이노우노 R4

포모도로 기법과 아두이노로 실제 만드는 방법

반응형

 

포모도로 기법(Pomodoro Technique)은 시간 관리 방법으로, 1980년대 프란체스코 치릴로(Francesco Cirillo)가 개발했습니다.

 

이 기법은 집중력을 높이고 생산성을 향상시키기 위해 작업을 25분 단위(1 포모도로)로 나누고, 각 구간 후 5분 휴식을 취하는 방식입니다. 4개의 포모도로를 완료하면 15~30분 긴 휴식을 갖습니다.

 

타이머(전통적으로 토마토 모양 타이머 사용)를 활용해 시간을 엄격히 관리하며, 방해 요소를 최소화하는 데 초점을 둡니다. "포모도로"는 이탈리아어로 토마토를 뜻합니다. 

 

 

회로도

 

 

 

사용자 설정 상수

 

 

 

전체 코드

 

// 3차 버전 : https://wokwi.com/projects/424093001412009985

/*
//01 ~ 03 개별 코드를 통합 코드 작성
// 코드리뷰에 따른 개선
매직 넘버 제거
중복 코드 합침
밀리초 계산 명확화
디스플레이 포맷팅 함수 분리
*/

#include <Arduino.h>
#include <TM1637.h>

// -------------- LED 핀번호 및 변수 선언 --------------
const int WORK_LED_PIN = 11;
const int BREAK_LED_PIN = 10;

// -------------- 부저 핀번호 및 변수 선언 --------------
const int BUZZER_PIN = 9;
const int BUZZER_FREQUENCY = 1000;
const int BUZZER_DURATION = 1000;

// -------------- 4자리 7세그먼트 LED 핀번호 및 변수 , 객체 선언 --------------
const int CLK_PIN = 2; // 변수명 수정 (7로 시작하는 변수명은 문법 오류)
const int DIO_PIN = 3; // 변수명 수정
TM1637 segment(CLK_PIN, DIO_PIN);

// -------------- 디버그 모드 설정 --------------
const bool DEBUG_MODE = false;

// -------------- 작업, 휴식간 상태머신 변수 선언 --------------
bool isBreakTime = false;
unsigned long previousTime = 0;

// const int workMinutes = 25;
// const int breakMinutes = 5;

// -------------- 시간 상수 선언( 사용자 시간 설정 부분 ) --------------
const unsigned long ONE_SECOND_MS = 1000;
const unsigned long ONE_MINUTE_MS = 60 * ONE_SECOND_MS;

unsigned long setWorkingTime = 25 * ONE_MINUTE_MS; // 25분으로 설정
unsigned long setBreakTime = 5 * ONE_MINUTE_MS;    // 5분 휴식 시간

void setup()
{
    Serial.begin(9600);

    pinMode(WORK_LED_PIN, OUTPUT);
    pinMode(BREAK_LED_PIN, OUTPUT);
    pinMode(BUZZER_PIN, OUTPUT);

    segment.init();
    segment.set(BRIGHT_TYPICAL);

    digitalWrite(WORK_LED_PIN, LOW);
    digitalWrite(BREAK_LED_PIN, LOW);
}

void loop()
{
    handleTimer(isBreakTime);
}

void handleTimer(bool isBreak)
{
    unsigned long currentTime = millis();

    // millis() 오버플로우 처리
    if (currentTime < previousTime)
    {
        previousTime = 0;
    }

    unsigned long elapsedTime = currentTime - previousTime;
    unsigned long targetTime = isBreak ? setBreakTime : setWorkingTime;

    digitalWrite(WORK_LED_PIN, !isBreak);
    digitalWrite(BREAK_LED_PIN, isBreak);

    handle7SegmentDisplay();

    if (elapsedTime >= targetTime)
    {
        isBreakTime = !isBreakTime;
        previousTime = currentTime;
        Serial.println(isBreakTime ? "작업 완료! 휴식 시간 시작" : "휴식 완료! 작업 시간 시작");
        tone(BUZZER_PIN, BUZZER_FREQUENCY, BUZZER_DURATION);
    }
}

void handle7SegmentDisplay()
{
    int minute = 0;
    int second = 0;
    unsigned long remainTime = 0;
    unsigned long totalTime;

    if (!isBreakTime)
    {
        totalTime = setWorkingTime;
        remainTime = setWorkingTime - (millis() - previousTime);
    }
    else
    {
        totalTime = setBreakTime;
        remainTime = setBreakTime - (millis() - previousTime);
    }

    // 시간이 음수값으로 가지 않도록
    if (remainTime < 0)
    {
        remainTime = 0;
    }

    minute = remainTime / ONE_SECOND_MS / 60;
    second = (remainTime / ONE_SECOND_MS) % 60;

    if (DEBUG_MODE)
    {
        Serial.print("남은 시간: ");
        Serial.print(minute);
        Serial.print(":");
        Serial.println(second);
    }

    if (totalTime >= ONE_MINUTE_MS)
    {
        // 특별한 경우 처리 제거 - 일반 계산 사용
        // 기존 조건문 삭제: if (!isBreakTime && (setWorkingTime == 25 * ONE_MINUTE_MS))

        // 분:초 형식으로 표시
        displayMinutesAndSeconds(minute, second);
    }
    else
    {
        // 초 단위로만 표시
        displayOnlySeconds(second);
    }
}

/**
 * 분:초 형식으로 7세그먼트에 시간 표시
 * @param minute 표시할 분
 * @param second 표시할 초
 */
void displayMinutesAndSeconds(int minute, int second)
{
    displayTwoDigits(0, minute); // 앞 두 자리에 분 표시
    displayTwoDigits(2, second); // 뒤 두 자리에 초 표시
}

/**
 * 초만 7세그먼트에 표시 (앞 두 자리는 00)
 * @param second 표시할 초
 */
void displayOnlySeconds(int second)
{
    segment.display(0, 0);
    segment.display(1, 0);
    displayTwoDigits(2, second); // 뒤 두 자리에만 초 표시
}

/**
 * 두 자리 숫자를 7세그먼트에 표시 (한 자리면 앞에 0 추가)
 * @param startPos 시작 위치 (0-3)
 * @param value 표시할 값 (0-99)
 */
void displayTwoDigits(int startPos, int value)
{
    if (value < 10)
    {
        segment.display(startPos, 0);
        segment.display(startPos + 1, value);
    }
    else
    {
        segment.display(startPos, value / 10);
        segment.display(startPos + 1, value % 10);
    }
}

 

 

 

 

 

 

참고 자료는 이곳에서 전체를 보실 수 있습니다.

 

 

https://youtube.com/shorts/ybCPCdGkfR8?si=TRL5WjcPE2Vmtzod

 

 

반응형

캐어랩 고객 지원

취업, 창업의 막막함, 외주 관리, 제품 부재!

당신의 고민은 무엇입니까? 현실과 동떨어진 교육, 실패만 반복하는 외주 계약, 아이디어는 있지만 구현할 기술이 없는 막막함.

우리는 알고 있습니다. 문제의 원인은 '명확한 학습, 실전 경험과 신뢰할 수 있는 기술력의 부재'에서 시작됩니다.

이제 고민을 멈추고, 캐어랩을 만나세요!

코딩(펌웨어), 전자부품과 디지털 회로설계, PCB 설계 제작, 고객(시장/수출) 발굴과 마케팅 전략으로 당신을 지원합니다.

제품 설계의 고수는 성공이 만든 게 아니라 실패가 만듭니다. 아이디어를 양산 가능한 제품으로!

귀사의 제품을 만드세요. 교육과 개발 실적으로 신뢰할 수 있는 파트너를 확보하세요.

지난 30년 여정, 캐어랩이 얻은 모든 것을 함께 나누고 싶습니다.

카카오 채널 추가하기

카톡 채팅방에서 무엇이든 물어보세요

당신의 성공을 위해 캐어랩과 함께 하세요.

캐어랩 온라인 채널 바로가기

캐어랩