Devin.KR

PWM 상태 표시

110분 안팎

학습 목표

가상 PWM의 duty와 주기를 검사하고 기록 상태별 LED 밝기를 바꿉니다.

개념

PWM 상태 표시의 계약을 구현합니다

LED가 켜짐과 꺼짐만 표시하면 기록기의 상태를 구분하기 어려울 수 있습니다. 이번 레슨은 정지 10%, 기록 75%라는 가상 PWM 정책을 추가합니다. 비율은 사용자가 상태를 구별하기 위한 연습 설정이고 제품의 밝기 정격이 아닙니다. 기존 GPIO LED는 모드 회귀 관찰에 남겨 두며 PWM 파형은 별도의 RAM 모델로 검사합니다. 실제 핀에 두 구동 경로를 연결하지 않습니다.

PWM은 주기 중 높은 레벨인 시간의 비율을 바꾸는 방식입니다. 여기서는 한 주기를 20 tick으로 나누고 high tick을 period 곱하기 duty 나누기 100으로 계산합니다. 나눗셈은 정수 버림입니다. 25%이면 5 tick이 높고 15 tick이 낮습니다. tick마다 반환하는 숫자 0·1은 가상 출력이며 실제 전압이나 LED 전류를 측정한 결과가 아닙니다.

pwm_set은 period 1~1000, duty 0~100을 받습니다. 잘못된 요청이면 0을 반환하고 기존 설정을 보존합니다. 범위를 넘는 요청을 자동으로 최대값에 맞추지 않는 계약입니다. 테스트에서 duty 101과 period 0을 거부한 뒤 이전 duty를 다시 읽어 확인합니다. 호출자가 오류를 처리할 수 있도록 실패를 정상 설정처럼 숨기지 않습니다.

pwm_level은 tick을 period로 나눈 나머지를 위상으로 사용합니다. 위상이 high tick보다 작으면 1이고 그 외에는 0입니다. tick 20은 period 20의 새 주기 시작이므로 tick 0과 같은 레벨입니다. 주기 끝에서도 high가 한 칸 더 생기면 비교의 작거나 같음 조건을 의심합니다. 주기는 0~19의 스무 위치이며 0~20의 스물한 위치가 아닙니다.

0%는 high tick이 0이라 모든 위치가 낮습니다. 100%는 high tick이 period라 모든 위치가 높습니다. 100%에서 마지막 한 칸을 낮게 남기는 구현은 period-1을 비교 기준으로 썼는지 점검합니다. 0%와 100%를 일반 비율과 별개로 시험하면 경계 오류를 쉽게 드러냅니다. 실물 타이머는 비교 레지스터의 끝점 동작이 다를 수 있어 해당 주변장치 문서로 확인해야 합니다.

period 20의 분해능은 한 칸에 5%입니다. 요청 33%는 high tick 6이 되어 실현 비율 30%입니다. 요청 값과 구현 가능한 비율을 나누어 기록합니다. 이번 기록 75%와 정지 10%는 각각 15칸과 2칸으로 정확히 표현됩니다. 모든 정수 퍼센트가 정확히 반영된다고 설명하면 정수 양자화를 놓칩니다. 더 세밀한 표시가 필요하면 period와 실제 타이머 클럭을 함께 검토합니다.

수집 100ms 주기와 LED PWM 주기는 서로 다른 일정입니다. pwm_level의 tick 단위는 아직 물리 시간이 정해지지 않았습니다. 20 tick만으로 몇 Hz라고 적을 수 없습니다. 실제 PWM 주파수는 tick을 만드는 클럭과 분주 설정이 있어야 계산됩니다. 센서 이벤트마다 한 번 LED를 반전하는 구현은 이 모델의 PWM과 다르며 수집 주기에 표시 파형을 묶습니다.

정지 상태에서도 10%를 요청하므로 약한 상태 표시를 의도합니다. 완전히 꺼져야 한다는 요구가 들어오면 정지 정책을 0%로 바꾸고 테스트도 제품 요구에 맞게 새로 승인합니다. 학습 실습에서는 주어진 10/75 계약을 유지합니다. 버튼이 눌린 원시 순간이 아니라 안정된 PRESS에서 모드가 바뀌고 그 결과로 duty가 바뀝니다. 물리 레벨과 표시 정책은 분리되어 있습니다.

기존 controller_init은 GPIO LED를 끄고 버튼을 초기화합니다. 새 timed_button이 성공할 때 PWM 정책을 적용합니다. HAL read나 write가 실패하면 컨트롤러 복사본을 확정하지 않고 PWM도 바꾸지 않습니다. 순차 모델에서의 상태 보존이며 하드웨어가 실패 전에 부분 출력했다면 물리 부작용을 되돌린다는 계약은 아닙니다. 실물 실패 정책은 다음 복구 모듈에서 더 다룹니다.

밝기와 duty가 같은 숫자 비율이라는 설명은 피합니다. LED 전류, 드라이버, 광학 응답, 관찰 조건에 따라 체감이 달라질 수 있습니다. 이번 테스트는 높은 tick 수를 셀 뿐 눈으로 본 밝기나 안전한 전류를 보증하지 않습니다. 서재의 모터 장은 PWM 적용 대상을 비교하는 데 읽고 LED 정책을 모터 속도나 서보 각도로 그대로 옮기지 않습니다. 각 부하의 입력 규격을 다시 확인합니다.

starter는 요청 duty를 저장하지 않고 0을 넣습니다. 함수가 성공 1을 반환해도 상태가 맞는지는 별도의 파형 검사로 확인합니다. FAIL high==5라면 설정 단계의 duty와 계산된 high tick을 살펴봅니다. 출력이 모두 낮을 때 반복 인덱스만 바꾸면 근본 원인을 놓칩니다. 저장된 설정, 위상 계산, 레벨 비교라는 세 부분을 순서대로 좁혀 봅니다.

누적 미션은 앞 모듈의 버튼·HAL·Buffer·기존 테스트를 포함합니다. 새 호출 경로는 timed_button, timer_poll, timed_consume 순입니다. 버튼 시작을 20ms에 확정한 뒤 0~1000ms 일정의 100~1000 이벤트를 소비하면 샘플 10개가 쌓입니다. 큐를 제때 소비하는 정상 사례와 소비가 멈춘 과부하 사례를 나눕니다. FIFO가 맞아도 손실 계수를 보고하지 않으면 운영 관찰은 불완전합니다.

미션 starter에는 순환 비교·손실 계수·PWM 저장 세 미완성 동작이 있습니다. 각각 별도 레슨의 수정 근거를 events.c에 적용하고 make test로 앞 모듈 회귀까지 확인합니다. 기존 controller_step의 기대값은 그대로 유지합니다. 새 이벤트 경로를 추가했다는 이유로 이전 버튼 튐 fixture를 지우지 않습니다. 다음 센서 통신 모듈은 이 소비 경로의 raw 공급 부분을 확장할 수 있습니다.

제출 기록에는 테스트 출력, 각 TODO 수정 이유, 100ms 예정선과 실제 샘플 시각의 차이, full의 손실 정책, PWM 20tick의 분해능을 적습니다. 실물 후속 항목으로 핀 mux, PWM 극성, 주파수, 드라이버 정격, 공유 큐 동기화와 ISR 실행 시간을 남깁니다. PC 검사 완료와 실물 확인 필요를 서로 다른 문장으로 씁니다. 동작을 보여 주는 작은 경계 사례가 긴 구현 설명보다 리뷰를 빠르게 만듭니다.

따라하기

새 테스트의 실패식 확인

starter 압축을 풀어 Makefile 위치에서 실행합니다. FAIL line 뒤의 조건을 읽고 events.c의 TODO를 수정합니다. 이 단계는 실패 지점을 관찰하므로 환경별 출력은 직접 기록합니다.

make -s events-test

완성 경로 재현

solution 압축의 독립 폴더에서 새 검사를 실행합니다. 테스트 소스의 조건과 출력 건수를 함께 확인합니다.

make -s events-test

실행 결과

timer-events: 91 cases, 0 failures

누적 회귀와 제출 근거

수정한 starter에서 전체 회귀를 실행합니다. README의 관찰 목록 중 이 레슨 경계 사례를 적고 정상 종료 코드를 기록합니다.

make test

확인 문제

실습

events.c의 pwm_set이 유효 duty를 저장하도록 구현합니다. 0/100%와 오류 요청 시 설정 보존을 확인하고 미션에서는 앞 두 레슨 수정도 적용합니다.

시작 코드·테스트 내려받기

실행 명령

make test

기대 결과

이전 회귀 및 timer-events 검사 0 failures, 종료 코드 0

모범 답안모범 답안 내려받기

더 읽기

면접 질문

  • PWM duty와 주기를 별도로 검사하는 이유를 설명해 주세요.