산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> VHDL

FPGA 기반 RC 서보 컨트롤러 설계: 정밀 PWM 구현

무선 조종(RC) 서보는 취미용 항공기, 자동차, 보트의 핵심입니다. 원격 무선 명령을 정밀한 각도 위치로 변환합니다. RC 시스템이 수십 년 된 만큼 업계 표준 인터페이스는 순수 디지털 프로토콜이 아닌 펄스 폭 변조(PWM)입니다. FPGA가 제공하는 결정론적 타이밍으로 고정밀 PWM 구현은 간단합니다. 이 글은 PWM을 사용하는 모든 RC 서보와 호환되는 제네릭 VHDL 서보 컨트롤러를 시뮬레이션 테스트벤치와 Lattice iCEstick FPGA 보드 실구현 예제와 함께 안내합니다.

RC 서보용 PWM 제어 원리

PWM 기초는 다른 곳에서 다루지만, RC 서보는 약간 다른 접근이 필요합니다. 서보는 전체 듀티 사이클을 무시하고 각 펄스의 하이 기간 지속시간만 샘플링합니다. 펄스 간 표준 간격은 20ms로 50Hz 주파수에 해당. 20ms 윈도우 내에서 서보가 읽는 펄스 폭은 일반적으로 1ms(최소 위치)~2ms(최대 위치)이나 제조사마다 정확한 값은 다릅니다.

FPGA 기반 RC 서보 컨트롤러 설계: 정밀 PWM 구현

위 그림은 타이밍 관계: 20ms 주기 반복, 각 펄스의 하이 타임이 서보 각도 위치에 직접 매핑.

VHDL 서보 컨트롤러

클럭 주파수, PWM 펄스 주파수, 최소/최대 펄스 폭(마이크로초), 극단 사이 이산 위치 수를 제네릭 파라미터로 받는 제네릭 VHDL 모듈 제작. FPGA 클럭이 메가헤르츠 대역이라 정수 카운터 연산으로 충분한 해상도 확보. 반올림 모호성 방지 위해 ieee.math_real 패키지의 round 함수 사용(영에서 멀어지는 방향 반올림).

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.math_real.round;

서보 모듈 엔티티 선언:

entity servo is generic ( clk_hz : real; pulse_hz : real; -- PWM pulse frequency min_pulse_us : real; -- microseconds at minimum position max_pulse_us : real; -- microseconds at maximum position step_count : positive -- Number of discrete positions ); port ( clk : in std_logic; rst : in std_logic; position : in integer range 0 to step_count - 1; pwm : out std_logic ); end servo;

position 입력이 서보를 최소(0)에서 최대(step_count-1) 설정으로 구동. pwm 출력은 서보 신호선(보통 노란색/흰색)에 연결. 대부분 FPGA가 3.3V 로직 출력이라 서보의 5V 입력에 맞추려면 레벨 시프터 필요.

선언부

마이크로초 단위 시간을 가장 가까운 정수 클럭 사이클 수로 변환하는 헬퍼 함수 정의:

function cycles_per_us (us_count : real) return integer is begin return integer(round(clk_hz / 1.0e6 * us_count)); end function;

이 함수로 핵심 타이밍 상수 계산:

constant min_count : integer := cycles_per_us(min_pulse_us); constant max_count : integer := cycles_per_us(max_pulse_us); constant min_max_range_us : real := max_pulse_us - min_pulse_us; constant step_us : real := min_max_range_us / real(step_count - 1); constant cycles_per_step : positive := cycles_per_us(step_us);

원하는 펄스 주파수로 동작하는 PWM 카운터 설정:

constant counter_max : integer := integer(round(clk_hz / pulse_hz)) - 1; signal counter : integer range 0 to counter_max; signal duty_cycle : integer range 0 to max_count;

클럭 사이클 카운팅

다음 프로세스가 프리러닝 카운터 구현:

COUNTER_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then counter <= 0; else if counter < counter_max then counter <= counter + 1; else counter <= 0; end if; end if; end if; end process;

PWM 출력 프로세스

PWM 출력은 현재 duty_cycle 값이 지시하는 카운터 사이클 수만큼 하이 유지:

PWM_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then pwm <= '0'; else pwm <= '0'; if counter < duty_cycle then pwm <= '1'; end if; end if; end if; end process;

듀티 사이클 계산

리셋 시 duty_cycle은 최소 펄스 폭 기본값. 그 외엔 position 입력으로부터 계산:

DUTY_CYCLE_PROC : process(clk) begin if rising_edge(clk) then if rst = '1' then duty_cycle <= min_count; else duty_cycle <= position * cycles_per_step + min_count; end if; end if; end process;

cycles_per_step이 정수로 반올림되지만, FPGA 클럭이 50Hz 펄스 레이트보다 수십 배 빠르므로 결과 오차 무시 가능.

서보 테스트벤치

설계 검증 위해 모든 위치 값을 수동으로 순회하며 파형 캡처하는 간단 테스트벤치 구축. 1MHz 테스트 클럭으로 시뮬레이션 가속하면서 현실적 타이밍 반영.

시뮬레이션 상수

constant clk_hz : real := 1.0e6; constant clk_period : time := 1 sec / clk_hz; constant pulse_hz : real := 50.0; constant pulse_period : time := 1 sec / pulse_hz; constant min_pulse_us : real := 1000.0; constant max_pulse_us : real := 2000.0; constant step_count : positive := 5;

DUT 신호

signal clk : std_logic := '1'; signal rst : std_logic := '1'; signal position : integer range 0 to step_count - 1; signal pwm : std_logic;

클럭 생성:

clk <= not clk after clk_period / 2;

DUT 인스턴스화

DUT : entity work.servo(rtl) generic map ( clk_hz => clk_hz, pulse_hz => pulse_hz, min_pulse_us => min_pulse_us, max_pulse_us => max_pulse_us, step_count => step_count ) port map ( clk => clk, rst => rst, position => position, pwm => pwm );

테스트벤치 시퀀서

시퀀서가 DUT 리셋 후 모든 위치 값 순회, 변경 간격 한 펄스 주기 대기. 시퀀스 완료 후 시뮬레이션 종료.

SEQUENCER : process begin wait for 10 * clk_period; rst <= '0'; wait for pulse_period; for i in 0 to step_count - 1 loop position <= i; wait for pulse_period; end loop; report "Simulation done. Check waveform."; finish; end process;

서보 시뮬레이션 파형

다음 스냅샷은 테스트벤치 파형. PWM 출력은 각 위치 값에 맞는 예상 펄스 폭으로 초기 카운터 사이클 동안만 하이.

FPGA 기반 RC 서보 컨트롤러 설계: 정밀 PWM 구현

전체 프로젝트 파일 다운로드로 시뮬레이션 재현 가능.

FPGA 구현 예제

Lattice iCEstick 보드에서 실제 TowerPro SG90 서보 구동. 서보가 5V 로직 레벨 필요하므로 FPGA 핀과 서보 신호선 사이에 레벨 시프터 사용.

최상위 모듈 엔티티

entity top is port ( clk : in std_logic; rst_n : in std_logic; -- Pull-up pwm : out std_logic ); end top;

신호와 상수

서보 펄스 폭 실험적 보정: 0.5ms~2.5ms로 180° 풀 스윕. 다음 상수는 iCEstick 클럭과 서보 파라미터 매칭.

constant clk_hz : real := 12.0e6; -- iCEstick clock constant pulse_hz : real := 50.0; constant min_pulse_us : real := 500.0; -- 0.5 ms constant max_pulse_us : real := 2500.0; -- 2.5 ms constant step_bits : positive := 8; -- 0 to 255 constant step_count : positive := 2**step_bits;

프리러닝 카운터 25비트 폭, 12MHz 클럭에서 랩 타임 약 2.8초.

constant cnt_bits : integer := 25; signal cnt : unsigned(cnt_bits - 1 downto 0);

모듈 연결:

signal rst : std_logic; signal position : integer range 0 to step_count - 1; signal rom_addr : unsigned(step_bits - 1 downto 0); signal rom_data : unsigned(step_bits - 1 downto 0);

서보 모듈 인스턴스화

SERVO : entity work.servo(rtl) generic map ( clk_hz => clk_hz, pulse_hz => pulse_hz, min_pulse_us => min_pulse_us, max_pulse_us => max_pulse_us, step_count => step_count ) port map ( clk => clk, rst => rst, position => position, pwm => pwm );

자체 래핑 카운터 인스턴스화

COUNTER : entity work.counter(rtl) generic map ( counter_bits => cnt_bits ) port map ( clk => clk, rst => rst, count_enable => '1', counter => cnt );

사인 ROM 인스턴스화

SINE_ROM : entity work.sine_rom(rtl) generic map ( data_bits => step_bits, addr_bits => step_bits ) port map ( clk => clk, addr => rom_addr, data => rom_data );

동시 할당으로 카운터, ROM, 서보 연결:

position <= to_integer(rom_data); rom_addr <= cnt(cnt'left downto cnt'left - step_bits + 1);

Lattice iCEstick에서 테스트

전체 회로 브레드보드 구성: FPGA 3.3V 출력을 레벨 시프터로 5V 변환해 서보에 연결. PWM 신호는 iCEstick 핀 119에 연결. 전원 인가 시 서보가 0°~180° 사이 부드럽게 진동하며 극단에서 잠시 정지. 오실로스코프 PWM 파형 영상으로 올바른 타이밍 확인.

FPGA 기반 RC 서보 컨트롤러 설계: 정밀 PWM 구현

마무리

VHDL로 PWM 서보 컨트롤러 구현하는 방법 여럿 있지만 정수 카운터 사용하면 합성 로직이 단순(카운터, 레지스터, 멀티플렉서만). 가장 흔한 함정은 32비트 산술에서 무음 오버플로이므로, 선택한 파라미터로 중간 계산이 범위 내에 있는지 항상 검증해야 합니다.

이 PWM 스타일은 RC 서보 전용. 듀티 사이클이 주파수보다 중요한 애플리케이션(아날로그 전력 제어 등)엔 다른 PWM 전략이 바람직.

아날로그 전력 제어 PWM 읽기:
VHDL로 PWM 컨트롤러 만들기

직접 해보시려면 아래 이메일 입력으로 완전한 VHDL 코드, ModelSim 테스트벤치, iCEcube2 프로젝트, 프로그래머 설정이 담긴 ZIP 아카이브 다운로드.

댓글로 의견 남겨주세요!

VHDL

  1. PWM 전력 컨트롤러: 펄스 폭 변조 램프 드라이버 제작
  2. VHDL PWM 컨트롤러 구현: 설계, 시뮬레이션, FPGA 데모
  3. VHDL TEXTIO 라이브러리로 텍스트 파일에서 FPGA 블록 RAM 초기화하기
  4. ppDAQC Pi-Play트에서 InitialState로 실시간 온도 데이터 스트리밍 – 헤드리스 라즈베리 파이
  5. 라즈베리 파이 대시보드로 집 온도 모니터링하기
  6. 단계별 가이드: IIoT로 PLC 데이터 추출하여 실시간 인사이트 확보하기
  7. 보안 FPGA SoC의 신뢰실행환경(TEE)으로 차량 내 AI 보안 강화
  8. 서보 컨트롤러 수리 가능할까? 전문가 인사이트 & 비용 효율적 솔루션
  9. 오사이-프리마(Osai-Prima) 전기 서보 드라이브 97942050N 'C축 드라이브 OK 아님' 에러 해결
  10. 아두이노 우노로 25kHz 4핀 PWM 팬 제어하기 - 제작, 코드 및 테스트