Hanya untuk bersenang-senang, dan untuk membuktikannya dapat dilakukan, saya menyelesaikan rutin perakitan AVR untuk menghitung sin (x) menghasilkan 24 bit (3 byte) dengan satu bit kesalahan. Sudut input dalam derajat dengan satu digit desimal, dari 000 hingga 900 (0 ~ 90,0) hanya untuk kuadran pertama. Ini menggunakan kurang dari 210 instruksi AVR dan berjalan rata-rata 212 mikrodetik, bervariasi dari 211 us (sudut = 001) hingga 213 us (sudut = 899).
Butuh beberapa hari untuk melakukan semuanya, lebih dari 10 hari (jam bebas) hanya memikirkan algoritma terbaik untuk perhitungan, mengingat mikrokontroler AVR, tanpa titik mengambang, menghilangkan semua divisi yang mungkin. Yang membutuhkan waktu lebih banyak adalah membuat nilai step-up yang tepat untuk bilangan bulat, untuk memiliki presisi yang baik, perlu meningkatkan nilai 1e-8 menjadi bilangan bulat biner 2 ^ 28 atau lebih. Setelah semua kesalahan penyebab presisi dan pembulatan ditemukan, meningkatkan resolusi perhitungan mereka dengan tambahan 2 ^ 8 atau 2 ^ 16, hasil terbaik terpenuhi. Saya pertama-tama mensimulasikan semua perhitungan di Excel dengan menjaga semua nilai sebagai Int (x) atau Putaran (x, 0) untuk mewakili secara tepat pemrosesan inti AVR.
Misalnya, dalam algoritme sudut harus dalam radian, inputnya dalam Derajat untuk memudahkan pengguna. Untuk mengonversi Derajat ke Radian, rumus sepele adalah rad = derajat * PI / 180, sepertinya bagus dan mudah, tetapi tidak, PI adalah angka yang tak terbatas - jika menggunakan beberapa digit itu akan membuat kesalahan pada output, pembagian dengan 180 membutuhkan Manipulasi bit AVR karena tidak memiliki instruksi pembagian, dan lebih dari itu, hasilnya akan memerlukan titik apung karena melibatkan angka jauh di bawah bilangan bulat 1. Misalnya, Radian 1 ° (derajat) adalah 0,017453293. Karena PI dan 180 adalah konstanta, mengapa tidak membalikkan hal ini untuk perkalian sederhana? PI / 180 = 0,017453293, kalikan dengan 2 ^ 32 dan hasilnya menjadi 74961320 konstan (0x0477D1A8), kalikan angka ini dengan sudut Anda dalam derajat, katakanlah 900 untuk 90 ° dan geser 4 bit ke kanan (÷ 16) untuk mendapatkan 4216574250 (0xFB53D12A), yaitu radian dari 90 ° dengan ekspansi 2 ^ 28, muat dalam 4 byte, tanpa satu divisi (kecuali 4 sedikit bergeser ke kanan). Di satu sisi, kesalahan yang termasuk dalam trik tersebut lebih kecil dari 2 ^ -27.
Jadi, semua perhitungan lebih lanjut perlu mengingatnya 2 ^ 28 lebih tinggi dan diurus. Anda perlu membagi hasil yang sedang berjalan dengan 16, 256 atau bahkan 65536 hanya untuk menghindarinya menggunakan byte kelaparan yang tidak perlu tumbuh yang tidak akan membantu resolusi. Itu adalah pekerjaan yang melelahkan, hanya menemukan jumlah bit minimum dalam setiap hasil perhitungan, menjaga hasil presisi sekitar 24 bit. Masing-masing dari beberapa perhitungan di mana dilakukan dalam try / error dengan bit yang lebih tinggi atau lebih rendah dihitung dalam aliran Excel, menonton jumlah keseluruhan bit kesalahan pada hasil dalam grafik yang menunjukkan 0-90 ° dengan makro menjalankan kode 900 kali, sekali per kesepuluh gelar. Pendekatan Excel "visual" itu adalah alat yang saya buat, banyak membantu untuk menemukan solusi terbaik untuk setiap bagian kode.
Misalnya, mengumpulkan hasil perhitungan khusus ini 13248737.51 hingga 13248738 atau hanya kehilangan desimal "0,51", seberapa besar itu akan mempengaruhi ketepatan hasil akhir untuk semua tes sudut 900 input (00.1 ~ 90.0)?
Saya dapat menjaga hewan yang terkandung dalam 32 bit (4 byte) pada setiap perhitungan, dan berakhir dengan keajaiban untuk mendapatkan ketepatan dalam 23 bit hasilnya. Saat memeriksa seluruh 3 byte hasil, kesalahannya adalah ± 1 LSB, luar biasa.
Pengguna dapat mengambil satu, dua atau tiga byte dari hasil untuk persyaratan presisi sendiri. Tentu saja, jika hanya satu byte sudah cukup, saya akan merekomendasikan untuk menggunakan tabel dosa 256 byte tunggal dan menggunakan instruksi AVR 'LPM' untuk mengambilnya.
Setelah urutan Excel berjalan mulus dan rapi, terjemahan terakhir dari Excel ke perakitan AVR membutuhkan waktu kurang dari 2 jam, seperti biasa Anda harus berpikir lebih dulu, bekerja lebih lambat.
Pada saat itu saya dapat menekan lebih banyak dan mengurangi penggunaan register. Kode aktual (bukan final) menggunakan sekitar 205 instruksi (~ 410 byte), menjalankan kalkulasi sin (x) rata-rata 212 us, clock pada 16MHz. Pada kecepatan itu dapat menghitung 4700+ sin (x) per detik. Tidak menjadi penting, tetapi dapat menjalankan gelombang sinus yang tepat hingga 4700Hz dengan 23 bit presisi dan resolusi, tanpa tabel pencarian.
Algoritma dasar didasarkan pada seri Taylor untuk sin (x), tetapi banyak dimodifikasi agar sesuai dengan niat saya dengan mikrokontroler AVR dan presisi dalam pikiran.
Bahkan jika menggunakan tabel 2.700 byte (900 entri * 3 byte) akan sangat menarik, apa yang menyenangkan atau pengalaman belajar tentang itu? Tentu saja, pendekatan CORDIC juga dipertimbangkan, mungkin nanti, intinya di sini adalah untuk memeras Taylor ke inti AVR dan mengambil air dari batu kering.
Saya ingin tahu apakah Arduino "sin (78.9 °)" dapat menjalankan Processing (C ++) dengan presisi 23 bit dalam waktu kurang dari 212 us dan kode yang diperlukan lebih kecil dari 205 instruksi. Mungkin jika C ++ menggunakan CORDIC. Sketsa Arduino dapat mengimpor kode perakitan.
Tidak masuk akal untuk mengirim kode di sini, nanti saya akan mengedit posting ini untuk menyertakan tautan web, mungkin di blog saya di url ini . Blog sebagian besar dalam bahasa Portugis.
Usaha hobi-tanpa-uang ini menarik, mendorong batas-batas mesin AVR hampir 16MIPS pada 16MHz, tanpa instruksi divisi, perkalian hanya dalam 8x8 bit. Ini memungkinkan untuk menghitung sin (x), cos (x) [= sin (900-x)] dan tan (x) [= sin (x) / sin (900-x)].
Di atas itu semua, ini membantu menjaga otak saya yang berusia 63 tahun dipoles dan diminyaki. Ketika remaja mengatakan 'orang tua' tidak tahu apa-apa tentang teknologi, saya menjawab "pikirkan lagi, siapa yang menurut Anda menciptakan basis untuk semua yang Anda nikmati hari ini?".
Bersulang