Pada artikel ini saya akan memberi tahu Anda caranya:- Buat proyek di STM32CubeMX dan atur timer untuk menangkap sinyal eksternal.
- Dekode sinyal PPM dari konsol model pesawat.
- Buat Perangkat Antarmuka Manusia di STM32 dan tulis deskriptor Laporan HID Anda.
- Terbang di simulator di quadrocopter balap. :)
Kata pengantar
Baru-baru ini, balapan FPV pada quadrocopters kelas 250 (FPV - First Person View) semakin populer. Angka 250 berarti jarak antara sumbu motor secara diagonal, tipikal dari helikopter kecil yang dapat bermanuver. Perangkat semacam itu dibangun di atas kerangka karbon tahan lama yang tahan jatuh dan tabrakan. Baling-baling dengan diameter 5-6 inci dengan langkah besar (sudut kemiringan bilah) ditempatkan pada motor yang kuat untuk penerbangan paling dinamis. Gambar dari camcorder pos analog ditransmisikan pada frekuensi 5,8 GHz ke monitor atau kacamata video pilot. Karena transmisi digital melalui WiFi menciptakan penundaan lama (200-300 ms), video selalu disiarkan pada saluran analog. Untuk merekam klip spektakuler, kamera aksi diletakkan di papan tulis (GoPro, Mobius, SJcam, Xiaomi Yi, dll.).Berikut ini beberapa video menarik tentang copters FPV:
Sebelum membangun mini quadrocopter saya, saya ingin terbang dengan simulator dan melihat apakah saya tertarik dengan balapan FPV. Untuk pelatihan, simulator FPV FreeRider sangat cocok . Itu tidak mahal, memiliki versi demo gratis dan, menurut pilot berpengalaman, sangat akurat meniru mekanisme penerbangan yang sebenarnya.Anda dapat mengontrol pesawat di simulator dari keyboard atau dari joystick. Keyboard tidak cocok untuk uji coba, karena tombol hanya dapat mengirimkan nilai diskrit (tombol ditekan / tidak ditekan) dan tidak mungkin untuk mentransmisikan nilai tengah yang bervariasi secara halus. Joystick dari konsol game dengan stik analog jauh lebih baik, tetapi mereka memiliki stik yang sangat kecil, yang tidak memungkinkan Anda untuk mengontrol perangkat dengan cukup akurat. Pilihan ideal untuk simulator adalah konsol model pesawat yang terhubung ke komputer melalui adaptor khusus, berkat sistem operasi yang melihatnya sebagai joystick.Saya sudah punya satu quadrocopter, dirakit untuk penerbangan santai dan fotografi, tetapi terlalu besar dan berat untuk balapan. Oleh karena itu, ada remote control - Turnigy 9X (dalam ilustrasi pertama). Di sisi belakang, ia memiliki konektor untuk menghubungkan adaptor yang menghasilkan sinyal PPM. Sinyal ini adalah pulsa pendek dengan interval dari 1 hingga 2 milidetik, durasi yang sesuai dengan posisi kontrol (lebih lanjut tentang hal itu di bagian decoding).Saya harus mengatakan bahwa adaptor untuk menghubungkan remote control dari PPM ke USB telah lama dirilis dan dijual dengan sekuat tenaga dan utama. Adaptor serupa di faktor bentuk flash drive dapat dibeli seharga $ 5 di Cina atau sedikit lebih mahal di toko-toko Rusia. Ada juga proyek adaptor sumber terbuka pada pengontrol AVR.Tetapi keinginan yang kuat untuk terbang segera datang kepada saya pada larut malam, ketika semua toko model pesawat Moskow sudah tutup. Saya tidak ingin menunggu di pagi hari, tidak ada waktu untuk meracuni dan menyolder papan dengan ATmega, jadi saya memutuskan untuk membuat adaptor PPM-USB pada papan STM32F3Discovery, yang sudah lama menganggur dan sudah dekat.Apa yang dibutuhkan
Untuk membuat adaptor, Anda perlu:Papan debug penemuan cukup mahal. Biaya F3 yang dijelaskan sekitar $ 20 dan kemampuannya berlebihan untuk proyek sederhana. Saya menggunakannya karena pada saat penulisan ini adalah satu-satunya papan dengan perangkat keras USB yang saya temukan di rumah. Bagi yang belum membelinya, saya dapat menyarankan Anda untuk memperhatikan papan miniatur dengan controller STM32F103C8T6 dari AliExpress seharga $ 3 dan programmer ST-Link dari sana. Prosesnya tidak berbeda dari yang dijelaskan dalam artikel. Kecuali jika perlu memilih pengontrol lain di awal, tunjukkan keberadaan resonator kuarsa dan gunakan pinout yang sedikit berbeda.Membuat proyek di STM32CubeMX
STM32Cube adalah paket yang dikembangkan oleh STMicroelectronics untuk mempermudah hidup para pengembang perangkat STM32. Ini terdiri dari utilitas grafis CubeMX, driver HAL, dan komponen Middleware.CubeMX adalah alat untuk membuat proyek dan menginisialisasi peripheral. Untuk memulai, cukup pilih controller, centang kotak untuk modul yang diperlukan, pilih mode yang diperlukan dalam menu dan masukkan nilai yang diinginkan di beberapa bidang. CubeMX akan menghasilkan proyek dan menghubungkan pustaka yang diperlukan untuk itu. Pengembang perangkat hanya akan menulis logika aplikasi.Driver HAL(Hardware Abstraction Layer) adalah API untuk bekerja dengan modul dan periferal mikrokontroler. HAL memungkinkan Anda untuk memisahkan lapisan atas aplikasi yang dibuat pengembang dari bekerja dengan register dan membuat kode program semudah mungkin antara keluarga pengontrol STM32.Middlewares , atau komponen perantara, termasuk sistem operasi FreeRTOS, perpustakaan untuk bekerja dengan sistem file, perpustakaan USB, TCP / IP, dll.Tampaknya sekarang mungkin untuk "memprogram dengan mouse" daripada secara manual menulis bit ke register. Tetapi kesederhanaan dan kemudahan tidak membatalkan fakta bahwa Anda perlu mempelajari dokumentasi, terutama dalam kasus di mana Anda perlu menekan kecepatan maksimum, konsumsi daya minimum atau menggunakan periferal dalam mode non-standar. STM32Cube belum mencakup 100% dari semua kemampuan mikrokontroler, tetapi sedang mendekati ini. STMicroelectronics memperbarui Cube dari waktu ke waktu, memperluas fungsi, dan memperbaiki bug. Oleh karena itu, jika Anda sudah menginstal Cube, periksa apakah itu versi terbaru.Pengaturan awal
Bekerja dengan proyek dimulai dengan pilihan pengontrol. Luncurkan STM32CubeMX, klik Proyek Baru . Pada tab MCU Selector , Anda dapat memilih pengontrol yang diinginkan dari filter. Karena kami memiliki papan debug yang sudah selesai, pada tab Selektor Papan , kami menemukan STM32F3Demangat . Setelah memilih papan, gambar controller dengan pin yang disorot dan ditandatangani akan muncul.Ada empat tab besar di bagian atas jendela:Pinout - untuk mengkonfigurasi fungsi pin dan mengatur modul. Kami ada di sana saat ini.Konfigurasi Jam - pengaturan jam, PLL, pembagi.Konfigurasi - konfigurasi periferal dan middleware yang lebih rinci.Kalkulator Konsumsi Daya - perhitungan daya yang dikonsumsi oleh mikrokontroler.
Di menu sebelah kiri pada tab Pinout , Anda dapat menggunakan periferal yang diinginkan, dan pada sirkuit pengontrol pilih fungsi untuk salah satu output mikrokontroler. Beberapa item di sebelah kiri adalah ikon peringatan. Ini berarti bahwa modul-modul (dalam hal ini ADC, DAC, OPAMP2, RTC) sekarang dapat digunakan secara tidak lengkap, karena beberapa outputnya sudah ditempati oleh fungsi-fungsi lain.Pin yang dikonfigurasikan ditandai dengan warna hijau pada sirkuit pengontrol. Karena kami memilih bukan pengontrol telanjang tanpa pengikat, tetapi papan debugging F3-Discovery yang sudah jadi, beberapa output sudah dikonfigurasikan, misalnya, tombol biru terhubung ke PA0, dan LED ke PE8 ... 15. Pin yang terhubung dengan beberapa perangkat eksternal pada Discovery disorot dalam warna oranye, tetapi modul periferal untuknya belum dikonfigurasikan. Seperti yang Anda lihat, ini adalah pin untuk USB, resonator kuarsa, SPI dan I2C untuk giroskop dan kompas, DP dan DM untuk USB. Kesimpulan abu-abu saat ini tidak digunakan, salah satunya dapat kami ajukan untuk tujuan kami.Seleksi input
Kami akan menangkap durasi pulsa, jadi input harus terhubung ke salah satu saluran timer. Selain itu, level sinyal dengan Turnigy 9X tidak 3.3V, seperti tegangan suplai dari STM32, tetapi 5V. Kami terlalu malas untuk menyolder pembagi tegangan, jadi Anda harus memilih input yang dapat menahan 5V (input ini disebut toleran 5V). Pin yang cocok dapat ditemukan di lembar data pada STM32F303VCT6 di bagian Pinouts dan Pin Description . Ada banyak timer di STM32F3, mereka tersebar di hampir semua pin. Opsi yang mudah adalah PC6. Itu dapat menahan 5 volt dan terletak di sudut kiri bawah papan, di sebelah GND. Tetapkan saluran 1 dari timer 3 TIM3_CH1 ke pin ini.Pengaturan jam
Agar USB berfungsi, mikrokontroler harus clock pada frekuensi yang sangat stabil, itulah sebabnya hampir semua perangkat USB memiliki resonator kuarsa. Stabilitas frekuensi generator RC internal tidak cukup untuk USB. Tetapi pada papan Discovery STM32F3, pengembang untuk beberapa alasan serakah dan tidak menaruh kuarsa. Namun, jika Anda mempelajari sirkuit dengan cermat , Anda dapat melihat bahwa sinyal MCO terhubung ke input PF0-OSC_IN , di mana kuarsa harus terhubung . Itu berasal dari programmer ST-Link di papan yang sama di mana ada kuarsa. The User Manual untuk F3 Discovery (UM1570) di OSC Jam bagian mengatakan bahwa 8 MHz sedang dikirim ke baris ini.
Dengan demikian, mikrokontroler clock dari sumber eksternal. Mode ini disebut Bypass. Di menu pengaturan periferal di bagian RCC , untuk mencatat Clock Kecepatan Tinggi, pilih BYPASS Clock Source .
Sebelum melanjutkan ke pengaturan jam yang lebih rinci, kami perhatikan di menu perangkat bahwa mikrokontroler akan bertindak sebagai perangkat USB.
Sekarang Anda dapat pergi ke tab besar berikutnya - Konfigurasi Jam . Di sini kita akan melihat diagram besar, yang menunjukkan sinyal jam apa yang ada dalam mikrokontroler, dari mana asalnya, bagaimana mereka bercabang, berkembang biak dan membelah. Dalam warna kuning, saya menyoroti parameter-parameter yang harus dicatat.
Periksa apakah frekuensi inputFrekuensi Input adalah 8 MHz.Kami mengatur saklar PLL Sumber Mux ke HSE (High Speed External) untuk clock dari sumber eksternal daripada sumber internal.PLL - Phase Lock Loop, atau PLL - loop-terkunci, berfungsi untuk melipatgandakan frekuensi eksternal beberapa kali. Atur pengganda PLLMul ke 9. Kemudian kita akan mencapai frekuensi maksimum yang mungkin untuk STM32F303 - 72 MHz.System Clock Mux harus dalam posisi PLLCLK sehingga frekuensi jam dikalikan dengan PLL.Untuk modul USB, 48 MHz diperlukan, jadi letakkan pembagi 1,5 di depan USB.Perhatikan frekuensinyaJam pengatur waktu APB1 di sisi kiri sirkuit. Itu pergi ke timer dan berguna bagi kita di masa depan.Jika ada frekuensi yang salah dikonfigurasi, melebihi nilai maksimum yang mungkin atau sakelar berada di posisi yang tidak valid, maka CubeMX akan menyorot tempat ini dengan warna merah.Pengaturan pengatur waktu
Untuk mengukur durasi pulsa, kami akan memulai penghitung waktu TIM3 dalam mode Pengambilan Input. Dalam Manual Referensi , di bawah bagian Timers tujuan umum (TIM2 / TIM3 / TIM4), ada diagram yang menggambarkan operasi timer. Dengan warna, saya menyoroti sinyal dan register yang digunakan dalam mode Capture Input.
Sinyal jam yang disorot dengan warna hijau terus-menerus memasuki register penghitung CNT dan menambah nilainya sebesar 1 setiap siklus jam. Dalam pembagi Prescaler PSC , frekuensi clock dapat menurun untuk jumlah yang lebih lambat. Sinyal eksternaldimasukkan ke TIMx_CH1 . Detektor tepiitu mengenali tepi sinyal input - transisi dari 0 ke 1 atau dari 1 ke 0. Saat mendaftarkan tepi, ia mengirimkan dua perintah yang disorot dengan warna kuning:- perintah untuk menulis nilai penghitung CNT ke daftar Capture / compare 1 register (CCR1) dan panggilan interupsi CC1I .- perintah untuk pengontrol mode Slave , dimana nilai CNT diatur ulang ke 0 dan hitung mundur dimulai lagi.Berikut ini adalah ilustrasi proses dalam timeline:
Ketika interupsi terjadi, kami akan melakukan tindakan dengan nilai yang ditangkap. Jika pulsa input datang terlalu sering, dan tindakan yang terjadi pada interrupt handler terlalu lama, maka nilai CCR1 dapat ditimpa sebelum kita membaca yang sebelumnya. Dalam hal ini, Anda perlu memeriksa bendera Overcapture atau menerapkan DMA (Akses Memori Langsung) ketika data dari CCR1 secara otomatis mengisi array yang disiapkan dalam memori. Dalam kasus kami, pulsa terpendek memiliki durasi 1 milidetik, dan pengendali interupsi akan sederhana dan pendek, jadi jangan khawatir tentang menimpa.Kembali ke tab Pinout dan atur timer TIM3 di menu Periferal .
Mode Slave: Mode Reset- Berarti pada suatu peristiwa timer akan diatur ulang ke 0.Sumber Pemicu: TI1FP1 - acara yang digunakan untuk mengatur ulang dan memulai timer adalah tepi sinyal yang diambil dari input TI1.ClockSource: Jam Internal - timer diberi clock dari generator internal mikrokontroler.Saluran 1: Mode pengambilan langsung input - interval pengambilan dari saluran pertama dalam register CCR1.Pada tab Konfigurasi besar berikutnya, kami akan membuat pengaturan timer tambahan.Prescaler adalah pembagi timer. Jika 0, frekuensinya diambil langsung dari clock bus APB clock - 72 MHz. Jika prescaler adalah 1, frekuensinya dibagi 2 dan menjadi 36 MHz. Atur pembagi ke 71 sehingga frekuensi dibagi dengan 72. Kemudian frekuensi timer akan menjadi 1 MHz dan interval akan diukur dengan resolusi 1 mikrodetik.Counter Period - atur nilai maksimum 16-bit 0xFFFF. Periode ini penting untuk menghasilkan slot waktu, misalnya, untuk PWM. Tetapi periode ini tidak penting untuk menangkap sinyal, kami akan membuatnya dikenal besar untuk setiap pulsa input.Pilihan Polaritas: Falling Edge - nilai timer akan ditangkap pada tepi jatuh dari sinyal input.Pada tab Pengaturan NVIC , letakkan dawTIM3 global interrupt , sehingga peristiwa yang terkait dengan timer ke-3 menghasilkan interupsi.Pengaturan perangkat USB
Kami telah mencatat bahwa pengontrol akan menjadi perangkat USB. Karena joystick milik kelas perangkat HID, di menu Middlewares -> USB_DEVICE, pilih Class For FS IP: Human Interface Device Class (HID) . Kemudian CubeMX akan menghubungkan perpustakaan untuk perangkat HID ke proyek.
Mari kita pergi ke pengaturan USB_DEVICE pada tab Konfigurasi di bagian Middlewares :ID Vendor dan ID Produk adalah dua pengidentifikasi 16-bit yang unik untuk setiap model perangkat USB. VID sesuai dengan produsen perangkat, dan masing-masing produsen menetapkan PID, dipandu oleh pertimbangan mereka sendiri. Saya tidak dapat menemukan daftar resmi VID dan PID, saya hanya menemukan basis pengenal yang didukung oleh penggemar. Untuk mendapatkan ID Vendor Anda sendiri, Anda harus pergi ke USB Implementers Forum di usb.org dan membayar beberapa ribu dolar. Perusahaan kecil atau pengembang sumber terbuka yang tidak mampu membeli VID mereka dapat meminta produsen chip USB dan secara resmi menerima pasangan VID / PID untuk proyek mereka. Layanan semacam itu ditawarkan, misalnya, oleh FTDI atau Laboratorium Silikon.Jika Anda menghubungkan dua perangkat dengan VID / PID yang sama, tetapi dari jenis yang berbeda (misalnya, satu adalah perangkat HID dan yang lainnya adalah Mass Storage), sistem operasi akan mencoba menginstal driver yang sama untuk mereka, dan setidaknya salah satu dari mereka tidak akan bekerja. Itulah sebabnya pasangan VID / PID untuk model perangkat yang berbeda harus unik.Karena kami tidak membuat perangkat untuk diri kami sendiri, kami tidak akan menjual dan mendistribusikannya, kami akan meninggalkan VID 0x0483, sesuai dengan STMicroelectronics, dan kami akan membuat PID kami sendiri. Secara default, CubeMX menawarkan PID 0x5710 untuk perangkat HID. Ganti, misalnya, dengan 0x57FF.Ganti string Produk dengan STM32 PPM-USB Adapter. Nama ini akan muncul di daftar perangkat di Panel Kontrol Windows. Kami belum akan mengubah nomor seri (S \ N).Ketika Windows mendeteksi ia mendeteksi perangkat dengan kombinasi VID, PID, dan S \ N yang belum pernah dilihat sebelumnya, sistem akan menginstal driver yang sesuai untuk itu. Jika kombinasi VID, PID dan S \ N telah digunakan, maka Windows secara otomatis mengganti driver yang sebelumnya digunakan. Anda dapat melihat ini, misalnya, ketika Anda menghubungkan flash drive ke USB. Pertama kali menghubungkan dan menginstal membutuhkan waktu. Pada koneksi berikutnya, drive mulai bekerja hampir secara instan. Namun, jika Anda menghubungkan instance lain dari drive Flash dari model yang sama, tetapi dengan nomor seri yang berbeda, sistem akan menginstal driver baru untuk itu, meskipun memiliki VID dan PID yang sama.Saya akan menjelaskan mengapa ini penting. Jika Anda membuat mouse USB pada STM32 dengan VID, PID, dan S \ N, menyambungkannya ke komputer, lalu membuat joystick USB tanpa mengubah VID, PID, dan S \ N, maka Windows akan menganggap perangkat baru sebagai mouse yang sudah digunakan dalam sistem, dan tidak akan menginstal driver joystick. Karenanya, joystick tidak akan berfungsi. Karena itu, jika Anda ingin mengubah jenis perangkat Anda, membiarkan VID / PID tidak berubah, pastikan untuk mengubah nomor seri.Pembuatan Proyek untuk IDE
Pengaturan terakhir yang perlu Anda buat adalah pengaturan pembuatan proyek. Ini dilakukan melalui Project -> Settings ... Di sana kita akan mengatur nama, folder tujuan dan IDE yang diinginkan, di mana CubeMX akan membuat proyek. Saya memilih MDK-ARM V5 , karena saya menggunakan Keil uVision 5. Pada tab Generator Kode , Anda dapat memeriksa kotak Salin hanya file perpustakaan yang diperlukan sehingga proyek tidak berantakan dengan file yang tidak perlu.Tekan tombol Project -> Hasilkan kode . CubeMX akan membuat proyek dengan kode yang dapat dibuka di Keil uVision dan dikompilasi dan di-flash tanpa pengaturan tambahan. Dalam file main.c dalam fungsi utama (kosong)fungsi telah dimasukkan untuk menginisialisasi jam, port, timer, dan USB. Di dalamnya, modul mikrokontroler dikonfigurasikan sesuai dengan mode yang kami atur di CubeMX.
Dalam kode, konstruksi semacam ini sering ditemukan:
(...)
Diasumsikan bahwa pengguna akan menyematkan kode mereka di bagian ini. Jika Simpan Kode Pengguna saat opsi pembuatan ulang diaktifkan di pengaturan proyek CubeMX , maka kode yang terlampir di antara garis-garis ini tidak akan ditimpa selama generasi kedua dari proyek yang ada. Sayangnya, hanya bagian yang dibuat oleh CubeMX yang disimpan. Bagian / * KODE PENGGUNA * / dibuat oleh pengguna akan hilang. Oleh karena itu, jika setelah menulis kode di IDE Anda ingin kembali ke CubeMX dan menghasilkan proyek lagi dengan pengaturan baru, saya sarankan untuk membuat salinan cadangan proyek.Dalam pengaturan firmware di uVision ( Flash -> Configure Flash Tools ) saya menyarankan Anda untuk mengaktifkan opsi Reset after flashsehingga mikrokontroler mulai segera setelah flashing. Secara default, ini dinonaktifkan, dan setelah setiap flashing, Anda harus menekan tombol Reset di papan tulis.
Decoding PPM
PPM - Pulse Position Modulation - metode pengkodean sinyal yang ditransmisikan, sangat tersebar luas dalam elektronik model pesawat terbang. Ini adalah urutan pulsa, interval waktu di antaranya sesuai dengan nilai numerik yang ditransmisikan.Menurut protokol ini, konsol mengirimkan informasi ke modul radio pengirim, yang dimasukkan ke konsol di bagian belakang. Banyak penerima yang ditempatkan di papan helikopter dapat mengirimkan sinyal kontrol untuk pengendali penerbangan melalui PPM. Selain itu, hampir semua konsol memiliki konektor untuk menghubungkan konsol kedua dalam mode trainer-student dan untuk menghubungkan konsol ke simulator, yang juga biasanya menggunakan PPM.Kami menulis sinyal dari output simulator Turnigy 9X dengan penganalisis logika:Setiap urutan mengkodekan status kontrol saat ini pada remote. Biasanya empat nilai pertama (juga disebut saluran) sesuai dengan posisi batang analog, dan yang berikutnya dengan posisi sakelar sakelar atau potensiometer.Posisi minimum kontrol sesuai dengan interval 1000 μs, maksimum - 2000 μs, posisi rata-rata - 1500 μs. Semburan pulsa, atau bingkai, dipisahkan oleh interval yang jauh lebih lama dan diikuti dengan periode 20-25 ms.Mari kita lihat lebih dekat sinyal:Seperti yang Anda lihat, tiga batang berada di posisi netral (1, 3, 4), dan satu di posisi ekstrem (2). Tiga sakelar sakelar mati (5, 6, 7), dan yang terakhir aktif (8). Mikrokontroler, yang bertindak sebagai adaptor, harus menangkap urutan seperti itu, menambahkan nilai ke array, dan mengirimkannya melalui USB sebagai perintah dari joystick. Mari kita menulis decoder urutan pulsa.Tangkap Gangguan
Setelah inisialisasi di main.c, sebelum loop sementara utama , mulai timer TIM3 dalam mode pengambilan Capture Input dari saluran 1, dengan generasi gangguan pengambilan. Untuk melakukan ini, gunakan fungsi yang sesuai dari HAL:HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
Struktur htim3 yang dideklarasikan di main.c adalah pengatur waktu TIM3, yang berisi semua struktur dan variabel yang terkait dengan timer: parameter untuk inisialisasi, pointer ke semua register timer (nilai penghitung, pembagi, semua pengaturan, bendera interupsi), penunjuk pada DMA handler yang bekerja dengan timer ini, dll. Pengembang tidak perlu mencari bit mana yang bertanggung jawab atas register apa dan secara manual mengatur dan meresetnya. Sudah cukup untuk menyerahkan pawang ke fungsi HAL. Perpustakaan HAL akan melakukan sisanya sendiri.Prinsip-prinsip struktur HAL dijelaskan secara lebih rinci dalam Deskripsi dokumen driver HAL STM32F3xx .(UM1786). Perlu dicatat bahwa perpustakaan HAL sendiri didokumentasikan dengan baik. Untuk memahami cara kerja HAL untuk timer dan cara menggunakannya, Anda dapat membaca komentar di file stm32f3xx_hal_tim.h dan stm32f3xx_hal_tim.c .Untuk setiap interupsi yang dihasilkan oleh timer TIM3, penangan TIM3_IRQHandler dipanggil . Itu terletak di file stm32f3xx_it.c , di mana HAL_TIM_IRQHandler handler , standar untuk semua timer, dipanggil di dalamnya, dan sebuah penunjuk ke struktur htim3 diteruskan ke sana.void TIM3_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim3);
}
Jika kita melihat ke dalam HAL_TIM_IRQHandler file stm32f3xx_hal_tim.c , kita melihat handler besar yang memeriksa flag interrupt untuk timer menyebabkan fungsi callback dan membersihkan flag setelah eksekusi. Jika peristiwa penangkapan terjadi , ia memanggil fungsi HAL_TIM_IC_CaptureCallback . Ini terlihat seperti ini:__weak void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
}
Ini berarti bahwa kita dapat menimpa fungsi ini di main.c . Oleh karena itu, masukkan panggilan balik ini sebelum fungsi int utama (void) :void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
};
Saya ingin melihat bagaimana interupsi dilakukan. Tambahkan untuk itu on-off cepat dari salah satu kesimpulan:void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, GPIO_PIN_SET);
__nop();__nop();__nop();__nop();__nop();__nop();
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, GPIO_PIN_RESET);
};
Pin PE8 telah diinisialisasi sebagai output. Antara menyalakan dan mematikan, instruksi __nop () dimasukkan , yang membentuk penundaan 1 siklus clock. Ini dilakukan agar penganalisa logika China $ 8 saya yang beroperasi pada 24 MHz tidak melewatkan pulsa terlalu pendek dari mikrokontroler 72 MHz. Sekarang kompilasi Proyek proyek -> Bangun target dan minta pengontrol Flash -> Unduh . Kami akan menghubungkan PPM dari remote ke PC6, dan melihat apa yang terjadi pada PC6 dan PE8 dengan penganalisis.Callback benar-benar dipanggil pada saat yang tepat - tepat setelah sinyal input telah beralih dari 1 ke 0. Jadi, semuanya dilakukan dengan benar.Menangkap dan memproses data yang diambil
Kami akan mengedit callback sehingga akan menambah setiap nilai ditangkap dengan captured_value penyangga tidak berubah. Jika timer menangkap nilai yang sangat besar (lebih dari 5000 μs), ini berarti bahwa jeda direkam, paket diterima secara keseluruhan dan dapat diproses. Nilai yang diproses ditambahkan ke array rc_data dari 5 elemen. Di empat pertama, posisi tongkat dikurangi ke kisaran [0; 1000], pada bit kelima, masing-masing bit diatur sesuai dengan sakelar sakelar, yang akan ditafsirkan sebagai menekan tombol pada gamepad.uint16_t captured_value[8] = {0};
uint16_t rc_data[5] = {0};
uint8_t pointer = 0;
uint8_t data_ready = 0;
...
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
uint8_t i;
uint16_t temp;
temp = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if ((temp > 5000) && (!data_ready))
{
pointer = 0;
for (i = 0; i < 4; i++)
{
if (captured_value[i] < 1000)
captured_value[i] = 1000;
else if (captured_value[i] > 2000)
captured_value[i] = 2000;
rc_data[i] = captured_value[i]-1000;
};
rc_data[4] = 0;
if (captured_value[4] > 1500)
rc_data[4] |= (1<<4);
if (captured_value[5] > 1500)
rc_data[4] |= (1<<5);
if (captured_value[6] > 1500)
rc_data[4] |= (1<<6);
if (captured_value[7] > 1500)
rc_data[4] |= (1<<7);
data_ready = 1;
}
else
{
captured_value[pointer] = temp;
pointer++;
};
if (pointer == 8)
pointer = 0;
}
Biarkan saya menjelaskan mengapa saya menempatkan bit yang sesuai dengan tombol tidak di 4 bit yang lebih rendah, tetapi di bit kelima hingga kedelapan. Dalam simulator, seharusnya menghubungkan gamepad dari Xbox, di mana tombol LB, RB, Start dan Back digunakan, dan mereka memiliki angka dari 5 hingga 8.Pada loop utama, flag data_ready akan terus diputar, dimana data akan dikirim ke komputer.while (1)
{
if (data_ready)
{
data_ready = 0;
}
}
Untuk memeriksa bagaimana ini bekerja, hubungkan remote control, kompilasi dan flash lagi, dan kemudian mulai debug Debug -> Mulai / Hentikan Sesi Debug .Membuka jendela untuk melacak variabel View -> Tonton Windows -> Tonton 1 dan add captured_value dan rc_data ada .Kami mulai debugging dengan Debug -> Jalankan perintah dan secara real time, bahkan tanpa menambahkan breakpoints, kita akan melihat bagaimana angka berubah setelah tongkat.Selanjutnya, Anda perlu mengirim data ke komputer dalam bentuk perintah joystick.Konfigurasikan perangkat HID dan buat deskriptor laporan HID
USB HID (Human Interface Device) adalah kelas perangkat untuk interaksi manusia-komputer. Ini termasuk keyboard, mouse, joystick, gamepad, panel sentuh. Keuntungan utama dari perangkat HID adalah bahwa mereka tidak memerlukan driver khusus di sistem operasi apa pun: Windows, OS X, Android, dan bahkan iOS (melalui adaptor USB-Lightning). Deskripsi terperinci dapat ditemukan dalam dokumen Device Class Definition for HID . Hal utama yang perlu kita ketahui untuk membuat adaptor PPM-USB adalah apa itu HID Report dan HID Report Descriptor .Perangkat HID mengirimkan paket byte ke komputer dalam format yang telah ditentukan. Setiap paket tersebut adalah Laporan HID. Perangkat memberi tahu komputer tentang format data ketika terhubung, mengirimkan HID Report Descriptor, deskripsi paket yang menunjukkan berapa banyak byte yang berisi paket dan tujuan dari setiap byte dan bit dalam paket. Misalnya, Laporan HID dari mouse sederhana terdiri dari empat byte: byte pertama berisi informasi tentang tombol yang ditekan, byte kedua dan ketiga berisi pergerakan relatif kursor sepanjang X dan Y, dan byte keempat berisi rotasi roda gulir. Deskriptor Laporan disimpan dalam memori pengontrol perangkat sebagai array byte.Sebelum membuat deskriptor, saya ingin membahas secara terpisah tentang terminologi. Dua istilah umum di lingkungan bahasa Inggris - joystick dan gamepad . Kata joystick biasanya disebut manipulator yang dipegang dengan satu tangan dan dimiringkan ke arah yang berbeda, dan gamepad adalah perangkat dengan tombol dan tongkat yang dipegang dengan dua tangan. Pengguna berbahasa Rusia biasanya menyebut joystick baik itu, maupun yang lain. Dalam deskripsi perangkat HID, ada perbedaan antara joystick dan gamepad. Konsol model pesawat terbang lebih mirip dalam tujuan fungsionalnya untuk gamepad, jadi di masa depan saya kadang-kadang akan menggunakan istilah "gamepad".Kami membuat proyek, yang menunjukkan bahwa perangkat akan bertindak sebagai Perangkat Antarmuka Manusia. Ini berarti bahwa perpustakaan USB HID terhubung ke proyek dan Descriptor Perangkat telah dihasilkan. Itu terletak di file usbd_hid.c , menjelaskan laporan mouse dan terlihat seperti ini:HID_Mouse_Report_Descriptor__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01,
0x09, 0x02,
0xA1, 0x01,
0x09, 0x01,
0xA1, 0x00,
0x05, 0x09,
0x19, 0x01,
0x29, 0x03,
0x15, 0x00,
0x25, 0x01,
0x95, 0x03,
0x75, 0x01,
0x81, 0x02,
0x95, 0x01,
0x75, 0x05,
0x81, 0x01,
0x05, 0x01,
0x09, 0x30,
0x09, 0x31,
0x09, 0x38,
0x15, 0x81,
0x25, 0x7F,
0x75, 0x08,
0x95, 0x03,
0x81, 0x06,
0xC0, 0x09,
0x3c, 0x05,
0xff, 0x09,
0x01, 0x15,
0x00, 0x25,
0x01, 0x75,
0x01, 0x95,
0x02, 0xb1,
0x22, 0x75,
0x06, 0x95,
0x01, 0xb1,
0x01, 0xc0
};
Membuat Descriptor Laporan HID secara manual sangat memakan waktu. Untuk memudahkan tugas, ada alat yang disebut HID Descriptor Tool (DT). Program ini dapat membuat deskriptor untuk perangkat Anda. Dalam arsipnya Anda dapat menemukan beberapa contoh deskriptor untuk perangkat yang berbeda.Berikut ini adalah artikel yang sangat bagus tentang membuat deskriptor HID Anda sendiri untuk mouse dan keyboard (dalam bahasa Inggris). Saya akan memberi tahu Anda dalam bahasa Rusia cara membuat pegangan untuk gamepad.Laporan HID yang dikirim oleh konsol harus berisi empat nilai 16-bit untuk dua sumbu stik analog dan 16 nilai satu-bit untuk tombol. Total 10 byte. Pegangannya yang dibuat di DT akan terlihat seperti ini: 0x05, 0x01,
0x09, 0x05,
0xa1, 0x01,
0x09, 0x01,
0xa1, 0x00,
0x09, 0x30,
0x09, 0x31,
0x15, 0x00,
0x26, 0xe8, 0x03,
0x75, 0x10,
0x95, 0x02,
0x81, 0x02,
0xc0,
0xa1, 0x00,
0x09, 0x33,
0x09, 0x34,
0x15, 0x00,
0x26, 0xe8, 0x03,
0x75, 0x10,
0x95, 0x02,
0x81, 0x02,
0xc0,
0x05, 0x09,
0x19, 0x01,
0x29, 0x10,
0x15, 0x00,
0x25, 0x01,
0x75, 0x01,
0x95, 0x10,
0x81, 0x02,
0xc0
Itu tidak kalah menakutkan dari deskriptor mouse. Tetapi jika Anda mengerti apa artinya setiap baris, semuanya ternyata cukup dimengerti dan logis.PENGGUNAAN menunjukkan bagaimana sistem harus menafsirkan data yang melangkah lebih jauh.Ada banyak jenis Penggunaan, mereka diurutkan ke dalam grup - Halaman Penggunaan. Karenanya, untuk memilih Penggunaan tertentu, Anda harus terlebih dahulu merujuk ke USAGE_PAGE yang sesuai. Tentang apa Penggunaan dapat ditemukan dalam dokumen Hid Usage Tables . Di bagian paling awal deskriptor, kami menunjukkan bahwa joystick akan dijelaskan:USAGE_PAGE (Generic Desktop)
USAGE (Game Pad)
KOLEKSI menggabungkan beberapa set data terkait.Pengumpulan Fisik digunakan untuk data yang terkait dengan satu titik geometris tertentu, misalnya, satu batang analog. Pengumpulan Aplikasi digunakan untuk menggabungkan berbagai fungsi dalam satu perangkat. Misalnya, keyboard dengan trackpad terintegrasi mungkin memiliki dua Koleksi Aplikasi. Kami hanya menjelaskan joystick, yang berarti bahwa koleksi tersebut akan menjadi satu:COLLECTION (Aplikasi)
...
END_COLLECTION
Setelah itu, Anda perlu menentukan bahwa elemen yang mengirimkan koordinat akan dijelaskan. Usage Pointer digunakan untuk menggambarkan mouse, joystick, gamepad, digitizers:PENGGUNAAN (Pointer)
Berikut ini adalah deskripsi batang analog yang digabungkan dalam koleksi:KOLEKSI (Fisik)
USAGE (X)
USAGE (Y)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1000)
REPORT_SIZE (16)
REPORT_COUNT (2)
INPUT (Data,Var,Abs)
END_COLLECTION
PENGGUNAAN di sini menunjukkan bahwa nilai-nilai bias digunakan sepanjang dua sumbu - X dan Y.LOGICAL_MINIMUM dan LOGICAL_MAXIMUM menentukan batas-batas mana nilai yang dikirimkan dapat bervariasi.REPORT_COUNT dan REPORT_SIZE ditetapkan, masing-masing, berapa banyak angka dan ukuran apa yang akan kita transfer, yaitu dua angka 16-bit.INPUT (Data, Var, Abs) berarti bahwa data berasal dari perangkat ke komputer, dan data ini dapat berubah. Nilai dalam kasus kami adalah absolut. Misalnya, nilai relatif berasal dari mouse untuk memindahkan kursor. Terkadang data digambarkan sebagai Const, bukan Var. Ini diperlukan untuk mengirimkan bit yang tidak signifikan. Misalnya, dalam laporan mouse dengan tiga tombol, 3 bit Var untuk tombol dan 5 bit Const ditransfer untuk menambah ukuran transfer ke satu byte.Seperti yang Anda lihat, deskripsi sumbu X dan Y dikelompokkan bersama. Mereka memiliki ukuran yang sama, batas yang sama. Stik analog yang sama dapat dijelaskan sebagai berikut, yang menjelaskan masing-masing sumbu secara terpisah. Deskriptor seperti itu akan bekerja sama dengan yang sebelumnya:KOLEKSI (Fisik)
MENGGUNAKAN (X) LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1000)
REPORT_SIZE (16)
REPORT_COUNT (1)
INPUT (Data, Var, Abs)
PENGGUNAAN (Y)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1000)
REPORT_SIZE (16)
REPORT_COUNT (1)
INPUT (Data, Var, Abs)
END_COLLECTION
Setelah stik pertama, stik analog kedua dijelaskan. Kapaknya memiliki Penggunaan yang berbeda sehingga Anda dapat membedakannya dari tongkat pertama - Rx dan Ry:KOLEKSI (Fisik)
USAGE (Rx)
USAGE (Ry)
LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1000)
REPORT_SIZE (16)
REPORT_COUNT (2)
INPUT (Data, Var, Abs)
END_COLLECTION
Sekarang Anda perlu menjelaskan beberapa tombol gamepad. Hal ini dapat dilakukan sebagai berikut:USAGE_PAGE (Tombol)
USAGE (Tombol 1)
USAGE (Tombol 2)
USAGE (Tombol 3)
...
USAGE (Tombol 16)
Rekaman rumit tombol dari jenis yang sama dapat dikurangi dengan menggunakan rentang Penggunaan:USAGE_PAGE (Tombol)
USAGE_MINIMUM (Tombol 1)
USAGE_MAXIMUM (Tombol 16)
Data yang dikirimkan oleh tombol adalah 16 nilai bit tunggal, bervariasi dari 0 hingga 1:LOGICAL_MINIMUM (0)
LOGICAL_MAXIMUM (1)
REPORT_SIZE (1)
REPORT_COUNT (16)
INPUT (Data,Var,Abs)
Urutan baris dalam deskriptor tidak ketat. Misalnya, Logical_Minimum dan Logical_Maximum dapat ditulis sebelum Penggunaan (Tombol), atau baris Report_Size dan Report_Count dapat ditukar.Penting bahwa perintah Input memiliki semua parameter yang diperlukan untuk transfer data (Penggunaan, Mimimum, Maksimum, Ukuran, Hitungan).Ketika deskriptor terbentuk, itu dapat diperiksa dengan perintah Parse Descriptor untuk kesalahan.Jika semuanya sudah beres, maka eksporlah dengan ekstensi h. Dalam file usbd_hid.c, ganti deskriptor dengan yang baru dan sesuaikan dengan usbd_hid.h ukuran deskriptor HID_MOUSE_REPORT_DESC_SIZE dari 74 hingga 61.Laporan dikirim menggunakan flag data_ready . Untuk inimain.c kita akan menyertakan file header usbd_hid.h dan dalam loop utama kita akan memanggil fungsi pengiriman laporan. Array rc_data bertipe uint16, jadi penunjuknya harus dilemparkan ke tipe 8-bit dan meneruskan ukuran 10 alih-alih 5.#include "usbd_hid.h"
...
while (1)
{
if (data_ready)
{
USBD_HID_SendReport(&hUsbDeviceFS, (uint8_t*)rc_data, 10);
data_ready = 0;
};
};
Kami mengkompilasi proyek dan mem-flashnya lagi.Koneksi dan penggunaan
Sambungkan kembali kabel USB dari konektor USB ST-LINK ke konektor USB USER. Windows akan mendeteksi perangkat baru dan secara otomatis menginstal driver. Mari kita pergi ke Control Panel -> Devices and Printers dan lihat perangkat Adaptor USB-PPM STM32 kami dengan ikon gamepad.Dalam pengaturan perangkat, Anda dapat melihat bagaimana salib bergerak melintasi bidang dan kolom bergerak setelah tongkat dipindahkan, dan simbol tombol menyala dari sakelar sakelar. Kalibrasi tidak diperlukan karena nilai minimum dan maksimum telah ditetapkan dalam deskriptor.Mulai FPV FreeRider, kita akan melihat bagaimana di layar utama pada gamepad virtual yang ditarik, tongkat bergerak sesuai dengan remote control kami. Jika sumbu tidak ditetapkan dengan benar karena alasan tertentu, Anda dapat mengkonfigurasi ulang di bagian Kontroler Pengalibrasi .Sakelar sakelar yang sesuai dengan tombol pada kendali jarak jauh digunakan untuk mengganti mode penerbangan (akrobatik / stabil), mengalihkan tampilan kamera (dari papan / dari tanah), memulai penerbangan dari awal atau menyalakan balapan untuk sementara waktu.Terbang!
Di video - hasil beberapa hari pelatihan saya. Sementara saya terbang dengan leveling otomatis, dan tidak dalam mode akrobatik, seperti yang dilakukan semua master balap FPV. Dalam mode acro, jika Anda melepaskan tongkat, copter tidak secara otomatis kembali ke posisi horizontal, tetapi terus terbang dengan sudut yang sama seperti terbang. Mengelola dalam mode acro jauh lebih sulit, tetapi Anda dapat mencapai kecepatan yang lebih besar, kemampuan manuver, membuat pergolakan di udara dan bahkan terbang terbalik.Untuk Charpu MastersSaya masih sangat jauh, tetapi saya terus berlatih dan saya dapat mengatakan dengan pasti bahwa gagasan helikopter mini balap semakin menarik bagi saya. Dan segera, saya pasti akan terlibat dalam konstruksi dan penerbangan tidak lagi dalam simulator, tetapi dalam kenyataan pahit, dengan tabrakan nyata, baling-baling rusak, mesin rusak dan baterai habis. Tapi ini topik untuk artikel lain :)
Proyek untuk Keil uVision 5 dan STM32CubeMX ada di GitHub .