Aritmatika titik tetap pada mikrokontroler

12

Seringkali kita menggunakan mikrokontroler untuk melakukan hal-hal dalam robot kita, tetapi perlu membuat beberapa perhitungan dalam desimal. Menggunakan variabel floating point sangat lambat, karena perpustakaan floating point perangkat lunak secara otomatis disertakan (kecuali Anda memiliki mikrokontroler high-end). Oleh karena itu, kami biasanya menggunakan aritmatika titik tetap.

Setiap kali saya melakukan ini, saya hanya menggunakan bilangan bulat, dan ingat di mana tempat desimalnya. Namun, perlu dipastikan bahwa semuanya konsisten, terutama ketika perhitungan melibatkan variabel di mana titik desimal berada di tempat yang berbeda.

Saya telah menerapkan fungsi atan2 titik tetap, tetapi karena saya mencoba memeras setiap tetes terakhir dengan presisi terbatas (16 bit), saya sering mengubah definisi di mana titik desimal berada, dan itu akan berubah ketika saya mengubahnya. Selain itu, saya akan memiliki beberapa konstanta, sebagai tabel kuasi, yang memiliki titik desimal tersirat di suatu tempat.

Saya ingin tahu apakah ada cara yang lebih baik. Apakah ada perpustakaan, atau kumpulan makro, yang dapat menyederhanakan penggunaan variabel titik tetap, membuat perkalian dan pembagian antara variabel campuran lebih mudah, dan memungkinkan deklarasi angka desimal atau ekspresi konstan, tetapi secara otomatis mengkonversi ke representasi titik tetap yang diinginkan pada saat kompilasi waktu?

ronalchn
sumber
1
Saya pikir ini sebenarnya lebih baik untuk stackoverflow karena solusinya agak generik dan tidak banyak hubungannya dengan robotika.
Shahbaz
1
@ Jakob - Perhatikan bahwa kedua pertanyaan itu ditutup tidak konstruktif.
Mark Booth
1
Ini adalah hal yang akan membuat C ++ sangat berguna untuk embedded system. Template akan menghasilkan kode yang benar dan optimal secara otomatis.
Rocketmagnet
1
Bisakah saya melihat fungsi atan Anda? Saya mencoba untuk mengatasi masalah konversi floating-to-fixed-point dalam penelitian akademis saya dan saya akan senang untuk mengambil celah untuk itu.
Joe Hass
1
Bagian @ronalchn dari Arduino (mikro AVR) bahasa diimplementasikan dalam C ++. Ada juga Perpustakaan AVR C ++ . Dan utas ini yang digunakan kompiler.
embedded.kyle

Jawaban:

7

Akan lebih baik jika kita bisa memberi tahu kompiler kisaran dan ketepatan dari setiap variabel input titik tetap (mungkin tidak ada dua yang memiliki titik radix di lokasi yang sama), dan itu akan secara otomatis - pada waktu kompilasi - menggunakan rentang yang benar dan operasi presisi dan pengubahan ukuran untuk nilai menengah dan nilai akhir dalam serangkaian perhitungan. Saya pernah mendengar desas-desus bahwa mungkin saja melakukannya dalam bahasa pemrograman Ada atau dalam templat C ++.

Sayangnya, yang paling dekat yang saya lihat adalah perpustakaan aritmatika titik-tetap yang mengharuskan Anda, programmer, untuk secara manual memilih representasi yang benar dan secara manual memverifikasi bahwa setiap operasi mempertahankan jangkauan dan presisi yang memadai. Kadang-kadang mereka membuat perkalian dan pembagian antara variabel campuran lebih mudah. Seperti:

David Cary
sumber
Hampir bisa dipastikan untuk melakukan ini menggunakan templat C ++.
Rocketmagnet
Saya sebenarnya sedang mengerjakan sesuatu seperti komentar "alangkah baiknya jika ..." Anda. Ini adalah plugin untuk gcc yang mengubah kode C titik-mengambang menjadi titik tetap, mengoptimalkan semua lokasi titik biner di sepanjang jalan. Saya punya makalah yang diserahkan ke jurnal ACM, dan satu lagi dalam persiapan. Jika Anda memiliki kode C untuk fungsi atan saya akan dengan senang hati mencobanya ... Saya bisa memberikan Anda kembali kode C yang menggunakan variabel integer dan melakukan semua hal-hal titik tetap.
Joe Hass
+1 untuk jawaban yang jauh lebih lengkap daripada saya. Saya telah mengedit tautan di tambang untuk memasukkan tautan ke suatu tempat untuk meminta kode sumber untuk menanggapi komentar Mark Booth. Anda mungkin ingin memperbarui tautan Anda juga. Saya akan melakukannya sendiri tetapi edit yang disarankan sedang dalam antrian dan memblokir saya.
embedded.kyle
1
@Rocketmagnet Sangat mungkin untuk menerapkan titik tetap menggunakan templat, lihat FixedPoints (penafian: Saya menulis ini, dan ini masih sangat 'muda').
Pharap
tautan gcc "a" rusak
Lesto
2

Saya telah menggunakan Perpustakaan TI IQMath untuk menerapkan titik-mengambang virtual pada titik tetap DSP mereka.

Texas Instruments TMS320C28x IQmath Library adalah kumpulan fungsi matematika yang sangat optimal dan presisi tinggi untuk programmer C / C ++ untuk secara mulus mem-porting algoritma floating-point ke dalam kode titik tetap pada perangkat TMS320C28x. Rutinitas ini biasanya digunakan dalam aplikasi real-time intensif komputasi di mana kecepatan eksekusi optimal dan akurasi tinggi sangat penting. Dengan menggunakan rutinitas ini Anda dapat mencapai kecepatan eksekusi yang jauh lebih cepat daripada kode setara yang ditulis dalam bahasa ANSI C standar. Selain itu, dengan menyediakan fungsi presisi tinggi siap pakai, perpustakaan TI IQmath dapat mempersingkat waktu pengembangan aplikasi DSP Anda secara signifikan.

Itu menggunakan beberapa hal spesifik TI tetapi saya juga menggunakan kode itu sebagai basis untuk mengimplementasikan matematika floating-point virtual pada mikrokontroler lainnya. Dibutuhkan sedikit usaha untuk port tetapi jauh lebih mudah daripada memulai dari awal.

tertanam.kyle
sumber
@downvoter Care mengomentari apa yang salah dengan jawaban saya?
embedded.kyle
+1: Pustaka ini lebih baik daripada yang dia gunakan sekarang ("cukup gunakan bilangan bulat"). Itu tidak melakukan semua pertanyaan awal yang ditanyakan, tapi saya pikir jawaban seperti ini (berguna, tetapi bukan solusi lengkap) tidak layak untuk downvote - kecuali solusi lengkap benar-benar ada (yang saya ragu dalam kasus ini ).
David Cary
Sepertinya bagi saya bahwa jawaban yang khusus untuk satu rangkaian perangkat dan hanya gratis seperti dalam bir daripada dalam ucapan adalah penggunaan terbatas untuk pengunjung masa depan.
Mark Booth
@MarkBooth Saya mengubah tautan dari pustaka C28x ke pustaka C64x. Jika Anda mengikuti tautan itu, Anda dapat meminta kode sumber. Anda memerlukan email perusahaan atau universitas untuk mendapatkan akses. Masih gratis seperti dalam bir dan bicara. Anda hanya perlu mengangkat tangan dan menunggu untuk dipanggil sebelum Anda dapat berbicara. Agak menyebalkan, tetapi begitu Anda memiliki kode sumber, itu bisa disesuaikan dengan prosesor apa pun yang Anda suka.
embedded.kyle
Terima kasih @ embedded.kyle kode sumber jelas lebih baik daripada biner saja, tetapi masih sedikit penggunaan umum jika lisensi hanya memungkinkan Anda untuk menggunakannya secara terbatas. Menurut halaman C6x Software Libraries bahwa sumber hanya dirilis di bawah Lisensi Komersial TI , yang hampir pasti tidak gratis seperti dalam ucapan .
Mark Booth
1

Ada sejumlah implementasi (tidak ada perpustakaan yang saya segera sadari) dari Binary Scaling (alias B-scaling)

Dalam hal ini, Anda menyimpan catatan mental (atau bahkan lebih baik, mendokumentasikan kode ...) di mana titik desimal berada, menggunakan shift untuk memindahkan titik desimal ke atas atau ke bawah.

Saya telah menggunakan B-scaling pada assembler pada proyek pertahanan, bahkan pada CPU terkecil sehingga dapat menjamin kesesuaiannya untuk hal lain ...

Andrew
sumber
Mungkin sesuatu seperti ini, tapi saya belum pernah melihatnya disebut b-scaling. Saya menganggapnya sebagai titik tetap - desimal tidak pernah mengambang karena meskipun titik desimal dapat berubah dalam proses perhitungan, setiap variabel selalu memiliki titik desimal tetap di lokasi tertentu
ronalchn
0

Jika Anda menggunakan bilangan bulat untuk mengingat di mana "titik" itu, mereka semacam menggunakan aritmatika titik mengambang. Titik tetap, benar-benar memiliki titik tetap .

atancosππ

Ini tergantung pada rentang nilai yang dibutuhkan aplikasi Anda, tetapi Anda mungkin ingin sepenuhnya pindah ke representasi titik tetap. Misalnya, alih-alih menyimpan nomor seperti ini:

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};

di mana numberbilangan bulat dan decimal_pointmengatakan di mana titik desimal berada, Anda dapat menyimpannya seperti ini:

struct num
{
    uint16_t integer;
    uint16_t fraction;
};

di mana bilangan bulat integer.fraction, yang memiliki penggunaan memori yang sama, rentang nilai yang lebih tinggi dan secara umum lebih mudah digunakan.

Shahbaz
sumber
Sebenarnya menyimpan titik desimal membuatnya lebih seperti titik mengambang. Biasanya titik desimal ditentukan pada waktu kompilasi, dan Anda mengubah antara representasi tergantung pada operasi Anda.
Jakob
Maksud saya tidak mengingat mengingat disimpan dalam variabel, maksud saya ingat mengingat saya ingat bagaimana menafsirkan hasil (dengan mengetahui di mana titik desimalnya)
ronalchn
@ronalchn, saya mengerti. Maksudmu sesuatu dengan #define, kan? Saya pikir Anda benar-benar menyimpannya dan dapat bervariasi berdasarkan pada seberapa besar atau kecil jumlah Anda.
Shahbaz
@ronalchn - apakah Anda berpikir tentang B-scaling? (lihat jawaban saya)
Andrew