DOCUMENTATION REVIEW · 2026-11-01

두 버튼 PWM: 누적값·입력 전이·출력 범위를 분리하기

버튼을 읽고 밝기값을 바꾼 뒤, 허용 범위로 제한한 값을 PWM 출력에 전달합니다. 짧은 지연 하나가 접점 바운스와 반복 입력 정책까지 해결하지는 않습니다.

원본의 안 보이는 핀을 추정하지 않고 예제 조건을 정합니다

저장된 코드 일부의 순서는 digitalRead → brightness 증감 → constrain(0,255) → analogWrite → delay(20)입니다. 핀 번호·증감폭·입력 극성은 확인되지 않았습니다. 아래는 원본 복원이 아닌 별도 예제로, 5 V Arduino UNO R3의 D2·D4를 INPUT_PULLUP 입력, D9를 외부 LED의 PWM 출력으로 정합니다. 버튼은 해당 입력과 GND 사이에 두어 눌림을 LOW로 읽는 조건입니다.

예제의 신호 경로 · 전원 OFF 상태에서 실제 핀·극성을 대조
D2 (pull-up) → UP button   → GND
D4 (pull-up) → DOWN button → GND
D9 (PWM) → resistor → LED anode
                      LED cathode → GND

Arduino의 PWM 목록에서 UNO R3의 D9는 PWM 지원 핀입니다. 기본 8비트 범위 0–255를 사용하며 다른 보드·해상도 설정에 이를 강제하지 않습니다. 이 핀의 PWM은 DAC의 연속 전압 출력이 아닙니다. 타이머를 공유하는 라이브러리와의 충돌도 따로 확인합니다.

LED 저항은 선택 LED의 순방향 전압과 허용 전류로 계산합니다. 설명용으로 5 V·2 V·1 kΩ이면 약 3 mA, 저항 손실은 약 9 mW입니다. 이는 가정값이며 실제 출력 전압, LED 편차와 보드 전체·포트 전류 한계를 확인해야 합니다. UNO R3의 핀당 20 mA 권장 동작 조건을 모든 핀에서 동시에 쓸 수 있는 총예산으로 해석하지 않습니다. 전력 LED·램프·모터를 이 핀에 직접 연결하는 예가 아닙니다.

누름 한 번과 누르고 있는 시간을 다른 정책으로 다룹니다

다음 모델은 입력이 30 ms 동안 안정된 뒤 새 눌림 한 번에 8만큼 바꾸고, 계속 누르고 있어도 반복하지 않습니다. 두 버튼이 동시에 눌린 안정 상태에서는 값을 유지합니다. 30 ms와 8은 이 설명용 모델의 선택이며 원본 수치나 모든 스위치의 적정값이 아닙니다. 시작할 때 이미 눌린 버튼은 초기 상태로만 받아들이고 밝기를 바꾸지 않습니다.

Arduino 디바운스 예제처럼 마지막 입력 변화 이후의 안정 시간을 추적해야 합니다. 단순히 매 반복에서 delay(20)을 호출했다는 사실로 안정된 눌림을 확인했다고 할 수 없습니다. 계속 누르면 반복할지, 어느 주기로 반복할지도 별도 상태와 시간 조건으로 정합니다.

증감 계산은 먼저 충분히 넓은 정수에서 하고 0–255로 제한한 뒤 출력합니다. 8비트 부호 없는 변수에서 0을 감소시켜 255로 감긴 다음 제한하면 의도와 다릅니다. 두 버튼 동시 입력의 처리 순서가 우연히 밝기를 바꾸지 않도록 정책을 명시합니다.

입력과 출력 사이의 상태만 독립적으로 검사합니다

아래 JavaScript는 검사 가능한 상태 전이 모델이며 Arduino 스케치가 아닙니다. up/down은 이미 눌림을 true로 정규화한 값, now는 32비트 밀리초 시각입니다. MCU에 옮길 때 입력 극성, 정수 폭, 시간 연산과 출력 API를 보드에 맞춰 구현해야 합니다.

function createState(up, down, now) {
  const button = pressed => ({ raw: pressed, stable: pressed, since: now });
  return { brightness: 0, up: button(up), down: button(down) };
}
function pressEdge(button, pressed, now) {
  if (pressed !== button.raw) {
    button.raw = pressed;
    button.since = now;
  }
  const elapsed = (now - button.since) >>> 0;
  if (button.stable !== button.raw && elapsed >= 30) {
    button.stable = button.raw;
    return button.stable;
  }
  return false;
}
function step(state, up, down, now) {
  const riseUp = pressEdge(state.up, up, now);
  const riseDown = pressEdge(state.down, down, now);
  if (!(state.up.stable && state.down.stable)) {
    const delta = riseUp ? 8 : riseDown ? -8 : 0;
    state.brightness = Math.max(0, Math.min(255, state.brightness + delta));
  }
  return state.brightness;
}

실제 펌웨어는 INPUT_PULLUP의 LOW를 눌림으로 바꾸고 두 입력을 같은 반복에서 읽은 뒤, 제한된 결과를 analogWrite(9, value)에 전달하는 구조로 연결할 수 있습니다. 이 모델은 unsigned 32비트 시간의 한 차례 순환을 처리하지만 2³² ms 이상 입력 검사를 하지 않은 상황까지 추론하지 않습니다.

논리 검사와 보드 동작 확인을 나눕니다

이 페이지의 코드 자체를 읽어 바운스, 안정 시간 경계, 길게 누름, 해제 후 재누름, 동시 누름, 상·하한과 시간 순환을 자동 검사했습니다. LED 저항의 위 계산과 논리 경로도 검산했습니다. Arduino 도구체인 컴파일·업로드·실제 보드 시험은 하지 않았습니다.

보드에서는 부팅 때의 밝기, 버튼 LOW/HIGH와 바운스, PWM의 0·중간·255, LED 전류·전압과 실제 밝기를 각각 확인해야 합니다. 같은 듀티 증가폭이 사람이 느끼는 밝기의 같은 증가폭을 보장하지 않습니다. 원본 Reel 전편이나 실제 밝기 시연을 확인한 것으로 기록하지 않습니다.

English summary. Normalize the button inputs, debounce state transitions, define simultaneous and held-button policies, then clamp a wide intermediate value before PWM output. The tested JavaScript model is not compiled Arduino firmware or a hardware validation.