Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Industrial programming >> VHDL

Merancang Pengontrol Servo RC Berbasis FPGA dengan PWM Presisi

Servo radio-kontrol (RC) adalah jantung pesawat, mobil, dan kapal hobi. Mereka menerjemahkan perintah radio jarak jauh menjadi posisi sudut yang tepat. Karena sistem RC sudah ada selama beberapa dekades, antarmuka standar industri adalah modulasi lebar pulsa (PWM) daripada protokol digital murni. Dengan waktu yang deterministik yang ditawarkan oleh lapangan gate array yang dapat diprogram (FPGA), implementasi PWM presisi tinggi adalah mudah. Artikel ini memandu Anda melalui pengontrol servo VHDL generik yang bekerja dengan setiap servo RC menggunakan PWM, termasuk testbench simulasi dan implementasi dunia nyata pada papan FPGA Lattice iCEstick.

Bagaimana PWM Kontrol untuk Servo RC Bekerja

Sementara dasar-dasar PWM dibahas di tempat lain, servo RC memerlukan pendekatan yang sedikit berbeda. Servo mengabaikan siklus kerja penuh; ia hanya mengecek durasi periode tinggi dari setiap pulsa. Interval standar di antara pulsa adalah 20 ms, yang sesuai dengan frekuensi 50 Hz. Dalam jendela 20 ms tersebut, servo membaca pulsa yang lebarnya biasanya berkisar dari 1 ms (posisi minimum) hingga 2 ms (posisi maksimum), meskipun nilai yang tepat bervariasi menurut produsen.

Merancang Pengontrol Servo RC Berbasis FPGA dengan PWM Presisi

Gambar ini menunjukkan hubungan waktu: periode 20 ms berulang, dan waktu tinggi dari setiap pulsa langsung memetakan ke posisi sudut servo.

Pengontrol Servo VHDL

Kami akan membangun modul VHDL generik yang menerima parameter generik untuk frekuensi clock, frekuensi pulsa PWM, lebar pulsa minimum dan maksimum (dalam mikrodetik), dan jumlah posisi diskrit antara ekstrem. Karena clock FPGA berjalan dalam rentang megahertz, aritmetika counter integer memberikan resolusi yang cukup. Untuk menghindari ambigu pembulatan, kami akan menggunakan fungsi round dari paket ieee.math_real, yang selalu membulatan jauh dari nol.

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

Berikut adalah deklarasi entitas untuk modul servo:

entity servo is generic ( clk_hz : real; pulse_hz : real; -- frekuensi pulsa PWM min_pulse_us : real; -- mikrodetik pada posisi minimum max_pulse_us : real; -- mikrodetik pada posisi maksimum step_count : positive -- Jumlah posisi diskrit ); port ( clk : in std_logic; rst : in std_logic; position : in integer range 0 to step_count - 1; pwm : out std_logic ); end servo;

Input position menggerakkan servo dari minimum (0) hingga pengaturan maksimum (step_count‑1). Output pwm terhubung ke kabel sinyal servo (biasanya kuning atau putih). Sebagian besar FPGA mengeluarkan logika 3.3 V, jadi penggeser level diperlukan untuk mencocokkan input 5 V servo.

Wilayah Deklaratif

Kami memulai dengan mendefinisikan fungsi pembantu yang mengubah waktu dalam mikrodetik ke bilangan integer siklus clock terdekat:

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

Menggunakan fungsi itu, kami menghitung konstanta timing inti:

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);

Selanjutnya, kami menyiapkan counter PWM yang berjalan pada frekuensi pulsa yang diinginkan:

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;

Menghitung Siklus Clock

Proses berikut mengimplementasikan counter bebas berjalan:

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;

Proses Output PWM

Output PWM dijalankan tinggi untuk sebanyak siklus counter yang ditentukan oleh nilai duty_cycle saat ini:

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;

Menghitung Siklus Kerja

Pada reset, duty_cycle default ke lebar pulsa minimum. Lainnya, itu dihitung dari input 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;

Meskipun cycles_per_step dibulatkan ke integer terdekat, kesalahan yang dihasilkan tidak signifikan karena clock FPGA sangat lebih cepat daripada laju pulsa 50 Hz.

Testbench Servo

Untuk memverifikasi desain, kami membangun testbench sederhana yang secara manual melangkah melalui semua nilai posisi dan menangkap gelombang. Clock tes 1 MHz mempercepat simulasi sambil masih mencerminkan waktu yang realistis.

Konstanta Simulasi

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;

Sinyal DUT

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

Pembangkit clock:

clk <= not clk after clk_period / 2;

Instantiasi 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 );

Sequencer Testbench

Sequencer mereset DUT, kemudian melalui semua nilai posisi, menunggu satu periode pulsa di antara perubahan. Setelah menyelesaikan urutan, simulasi berakhir.

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;

Gelombang Simulasi Servo

Cuplikan berikut menunjukkan gelombang testbench. Output PWM hanya tinggi untuk siklus counter terawal, cocok dengan lebar pulsa yang diharapkan untuk setiap nilai posisi.

Merancang Pengontrol Servo RC Berbasis FPGA dengan PWM Presisi

Unduh file proyek lengkap untuk mereproduksi simulasi.

Contoh Implementasi FPGA

Selanjutnya, kami menggerakkan servo TowerPro SG90 nyata dari papan Lattice iCEstick. Servo membutuhkan level logika 5 V, jadi kami menggunakan penggeser level di antara pin FPGA dan kabel sinyal servo.

Entitas Modul Top

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

Sinyal dan Konstanta

Kami mengkalibrasi lebar pulsa servo secara eksperimental: 0,5 ms hingga 2,5 ms menghasilkan ayunan 180° penuh. Konstanta berikut cocok dengan parameter clock dan servo iCEstick.

constant clk_hz : real := 12.0e6; -- clock iCEstick 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 hingga 255 constant step_count : positive := 2**step_bits;

Counter bebas berjalan 25 bit lebar, memberikan waktu wrap sekitar 2,8 detik pada clock 12 MHz.

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

Menghubungkan modul:

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);

Instantiasi Modul Servo

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 );

Instantiasi Counter Self-Wrapping

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

Instantiasi Sine 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 );

Tugas konkuren menghubungkan counter, ROM, dan servo bersama:

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

Pengujian pada Lattice iCEstick

Seluruh rangkaian di breadboard: output 3,3 V FPGA di-level-shift ke 5 V untuk servo. Sinyal PWM terhubung ke pin 119 pada iCEstick. Khi dinyalakan, servo berosilasi halus antara 0° dan 180°, berhenti sejenak di ekstrem. Video gelombang PWM pada osiloskop menunjukkan waktu yang benar.

Merancang Pengontrol Servo RC Berbasis FPGA dengan PWM Presisi

Pikiran Akhir

Ada banyak cara untuk mengimplementasikan pengontrol servo PWM dalam VHDL, tetapi menggunakan counter integer menjaga logika yang dihasilkan tetap sederhana—hanya counter, register, dan multiplexer. Penggolongan yang paling sering terjadi adalah overflow diam dalam aritmetika 32-bit, jadi selalu verifikasi bahwa perhitungan perantara tetap dalam batas untuk parameter yang Anda pilih.

Perhatikan bahwa gaya PWM ini disesuaikan untuk servo RC. Untuk aplikasi di mana siklus kerja lebih penting daripada frekuensi (misalnya, kontrol daya analog), strategi PWM yang berbeda lebih disarankan.

Baca tentang kontrol daya analog menggunakan PWM di sini:
Cara membuat pengontrol PWM dalam VHDL

Siap mencoba sendiri? Unduh arsip ZIP yang berisi kode VHDL lengkap, testbench ModelSim, proyek iCEcube2, dan konfigurasi programmer dengan memasukkan alamat email Anda di bawah ini.

Beritahu saya apa pendapat Anda di komentar!

VHDL

  1. Pengontrol Daya PWM: Buat Driver Lampu Modulasi Lebar Pulsa
  2. Implementasi Pengontrol PWM dalam VHDL: Desain, Simulasi, dan Demo FPGA
  3. Menginisialisasi Block RAM FPGA dari Berkas Teks dengan Pustaka TEXTIO VHDL
  4. Streaming Data Suhu Real-Time dari ppDAQC Pi-Plate ke InitialState dengan Raspberry Pi Tanpa Monitor
  5. Memantau Suhu Rumah dengan Dashboard Raspberry Pi
  6. Panduan Langkah demi Langkah: Mengekstrak Data PLC dengan IIoT untuk Wawasan Real-Time
  7. Mengamankan AI Dalam Kabin dengan Lingkungan Eksekusi Terpercaya pada SoC FPGA Aman
  8. Dapatkah Pengontrol Servo Anda Diperbaiki? Wawasan Ahli & Solusi Hemat Biaya
  9. Mengatasi Error 'C Axis Drive Not OK' pada Osai-Prima Electro Servo Drive 97942050N
  10. Kontrol Kipas PWM 4 Pin 25 kHz dengan Arduino Uno – Bangun, Kode & Uji