Để giải trí, và để chứng minh điều đó có thể được thực hiện, tôi đã hoàn thành một quy trình lắp ráp AVR để tính kết quả sin (x) trong 24 bit (3 byte) với một bit lỗi. Góc đầu vào tính bằng độ với một chữ số thập phân, từ 000 đến 900 (0 ~ 90.0) chỉ cho góc phần tư thứ nhất. Nó sử dụng ít hơn 210 lệnh AVR và chạy trung bình là 212 micro giây, thay đổi từ 211us (angle = 001) đến 213us (angle = 899).
Phải mất vài ngày để làm tất cả, hơn 10 ngày (giờ rảnh) chỉ nghĩ về thuật toán tốt nhất để tính toán, xem xét bộ vi điều khiển AVR, không có điểm nổi, loại bỏ tất cả các phân chia có thể. Điều cần nhiều thời gian hơn là tạo ra các giá trị tăng dần phù hợp cho các số nguyên, để có độ chính xác tốt, nó cần phải tăng các giá trị từ 1e-8 lên các số nguyên nhị phân 2 ^ 28 trở lên. Khi tất cả các lỗi thủ phạm của độ chính xác và làm tròn đã được tìm thấy, tăng độ phân giải tính toán của chúng thêm 2 ^ 8 hoặc 2 ^ 16, kết quả tốt nhất đã được đáp ứng. Trước tiên tôi đã mô phỏng tất cả các tính toán trên Excel, đảm bảo có tất cả các giá trị là Int (x) hoặc Round (x, 0) để thể hiện chính xác quá trình xử lý lõi AVR.
Ví dụ, trong thuật toán, góc phải tính bằng Radian, đầu vào tính theo Độ để tạo điều kiện thuận lợi cho người dùng. Để chuyển đổi Độ sang Radian, công thức tầm thường là rad = độ * PI / 180, có vẻ hay và dễ dàng, nhưng thực tế không phải vậy, PI là một số vô hạn - nếu sử dụng vài chữ số, nó sẽ tạo ra lỗi ở đầu ra, chia 180 Thao tác bit AVR vì nó không có lệnh chia, và hơn thế nữa, kết quả sẽ yêu cầu dấu phẩy động vì liên quan đến các số ở dưới số nguyên 1. Ví dụ, Radian của 1 ° (độ) là 0,017453293. Vì PI và 180 là hằng số, tại sao không đảo ngược điều này để nhân đơn giản? PI / 180 = 0,017453293, nhân nó với 2 ^ 32 và kết quả là hằng số 74961320 (0x0477D1A8), nhân số này với góc của bạn theo độ, giả sử 900 cho 90 ° và dịch chuyển đúng 4 bit (÷ 16) để thu được 4216574250 (0xFB53D12A), đó là radian của 90 ° với độ mở rộng 2 ^ 28, vừa với 4 byte, không chia một byte (trừ 4 byte dịch chuyển bit phải). Theo một cách nào đó, lỗi bao gồm trong thủ thuật đó nhỏ hơn 2 ^ -27.
Vì vậy, tất cả các tính toán tiếp theo cần phải nhớ nó cao hơn 2 ^ 28 và chăm sóc nó. Bạn cần chia kết quả khi đang di chuyển cho 16, 256 hoặc thậm chí 65536 chỉ để tránh việc sử dụng các byte đói không cần thiết sẽ không giúp giải quyết. Đó là một công việc khó khăn, chỉ cần tìm số lượng bit tối thiểu trong mỗi kết quả tính toán, giữ cho kết quả chính xác khoảng 24 bit. Mỗi một trong số các phép tính được thực hiện trong thử / lỗi với số bit cao hơn hoặc thấp hơn trong luồng Excel, xem tổng số bit lỗi ở kết quả trong biểu đồ hiển thị 0-90 ° với macro chạy mã 900 lần, một lần một phần mười của một mức độ. Cách tiếp cận Excel "trực quan" đó là một công cụ tôi tạo ra, đã giúp rất nhiều để tìm ra giải pháp tốt nhất cho mọi phần của mã.
Ví dụ: làm tròn kết quả tính toán cụ thể này 13248737.51 đến 13248738 hoặc chỉ mất các số thập phân "0,51", nó sẽ ảnh hưởng đến độ chính xác kết quả cuối cùng của tất cả các phép thử 900 góc (00.1 ~ 90.0) như thế nào?
Tôi đã có thể giữ con vật chứa trong vòng 32 bit (4 byte) trên mỗi phép tính và kết thúc bằng phép thuật để có được độ chính xác trong vòng 23 bit của kết quả. Khi kiểm tra toàn bộ 3 byte kết quả, sai số là ± 1 LSB, chưa xử lý.
Người dùng có thể lấy một, hai hoặc ba byte từ kết quả cho các yêu cầu chính xác của chính nó. Tất nhiên, nếu chỉ cần một byte là đủ, tôi khuyên bạn nên sử dụng một bảng sin 256 byte duy nhất và sử dụng hướng dẫn 'LPM' của AVR để lấy nó.
Khi tôi đã có chuỗi Excel chạy trơn tru và gọn gàng, bản dịch cuối cùng từ lắp ráp Excel sang AVR mất chưa đầy 2 giờ, như thường lệ bạn nên suy nghĩ nhiều hơn trước, làm việc ít hơn sau.
Lúc đó tôi đã có thể siết chặt hơn nữa và giảm việc sử dụng thanh ghi. Mã thực tế (không phải cuối cùng) sử dụng khoảng 205 lệnh (~ 410 byte), chạy phép tính sin (x) trung bình là 212us, xung nhịp ở mức 16 MHz. Với tốc độ đó, nó có thể tính được 4700+ sin (x) mỗi giây. Không quan trọng, nhưng nó có thể chạy một chuỗi hình chính xác lên đến 4700Hz với độ chính xác và độ phân giải 23 bit, không có bất kỳ bảng tra cứu nào.
Thuật toán cơ sở dựa trên loạt Taylor cho sin (x), nhưng đã sửa đổi rất nhiều để phù hợp với ý định của tôi với bộ vi điều khiển AVR và độ chính xác trong tâm trí.
Ngay cả khi sử dụng bảng 2700 byte (900 mục * 3 byte) sẽ có tốc độ hấp dẫn, trải nghiệm thú vị hoặc học tập trên đó là gì? Tất nhiên, cách tiếp cận CORDIC cũng đã được xem xét, có thể sau đó, vấn đề ở đây là ép Taylor vào lõi AVR và lấy nước từ một tảng đá khô.
Tôi tự hỏi nếu Arduino "sin (78,9 °)" có thể chạy Xử lý (C ++) với độ chính xác 23 bit trong ít hơn 212us và mã cần thiết nhỏ hơn 205 lệnh. Có thể nếu C ++ sử dụng CORDIC. Bản phác thảo Arduino có thể nhập mã lắp ráp.
Không có ý nghĩa để gửi mã ở đây, sau này tôi sẽ chỉnh sửa bài đăng này để bao gồm một liên kết web đến nó, có thể trên blog của tôi tại url này . Blog chủ yếu bằng tiếng Bồ Đào Nha.
Liên doanh không có sở thích này rất thú vị, đẩy các giới hạn của động cơ AVR gần 16MIPS lên 16 MHz, không có hướng dẫn phân chia, nhân chỉ trong 8 x 8 bit. Nó cho phép tính sin (x), cos (x) [= sin (900-x)] và tan (x) [= sin (x) / sin (900-x)].
Trên tất cả, điều này đã giúp giữ cho bộ não 63 tuổi của tôi được đánh bóng và bôi dầu. Khi thanh thiếu niên nói rằng 'người già' không biết gì về công nghệ, tôi trả lời "hãy nghĩ lại, bạn nghĩ ai đã tạo ra cơ sở cho mọi thứ bạn thích ngày hôm nay?".
Chúc mừng