Apenas por diversão, e para provar que isso pode ser feito, concluí uma rotina de montagem do AVR para calcular os resultados sin (x) em 24 bits (3 bytes) com um bit de erro. O ângulo de entrada está em graus com um dígito decimal, de 000 a 900 (0 ~ 90,0) apenas para o primeiro quadrante. Ele usa menos de 210 instruções AVR e executa em média 212 microssegundos, variando de 211us (ângulo = 001) a 213us (ângulo = 899).
Demorou vários dias para fazer tudo, mais de 10 dias (horas livres), apenas pensando no melhor algoritmo para o cálculo, considerando o microcontrolador AVR, sem ponto flutuante, eliminando todas as divisões possíveis. O que levou mais tempo foi criar os valores de aumento corretos para números inteiros; para ter uma boa precisão, é necessário aumentar os valores de 1e-8 para números inteiros binários 2 ^ 28 ou mais. Depois que todos os erros de precisão e arredondamento foram encontrados, aumentou sua resolução de cálculo em 2 ^ 8 ou 2 ^ 16 extras, os melhores resultados foram alcançados. Primeiro simulei todos os cálculos no Excel, tendo todos os valores como Int (x) ou Arredondado (x, 0) para representar exatamente o processamento do núcleo do AVR.
Por exemplo, no algoritmo, o ângulo deve estar em Radianos, a entrada está em Graus para facilitar o usuário. Para converter graus em radianos, a fórmula trivial é rad = degrees * PI / 180, parece fácil e agradável, mas não é, PI é um número infinito - se usar alguns dígitos, criará erros na saída, a divisão por 180 exige Manipulação de bits AVR, uma vez que não possui instrução de divisão e, além disso, o resultado exigiria ponto flutuante, pois envolve números muito abaixo do número inteiro 1. Por exemplo, Radiano de 1 ° (grau) é 0,017453293. Como PI e 180 são constantes, por que não reverter isso para uma multiplicação simples? PI / 180 = 0,017453293, multiplique por 2 ^ 32 e resulta como uma constante 74961320 (0x0477D1A8), multiplique esse número pelo seu ângulo em graus, digamos 900 para 90 ° e mova-o 4 bits para a direita (÷ 16) para obter 4216574250 (0xFB53D12A), que são os radianos do 90 ° com expansão 2 ^ 28, cabem em 4 bytes, sem uma única divisão (exceto os 4 mudança de bits para a direita). De certa forma, o erro incluído nesse truque é menor que 2 ^ -27.
Portanto, todos os cálculos adicionais precisam lembrar que é 2 ^ 28 maior e resolvidos. Você precisa dividir os resultados on-the-go por 16, 256 ou até 65536, apenas para evitar o uso desnecessário de bytes de fome crescentes que não ajudariam na resolução. Foi um trabalho minucioso, encontrar a quantidade mínima de bits em cada resultado de cálculo, mantendo a precisão dos resultados em torno de 24 bits. Cada um dos vários cálculos realizados em tentativa / erro com bits mais altos ou mais baixos conta no fluxo do Excel, observando a quantidade geral de bits de erro no resultado em um gráfico mostrando 0-90 ° com uma macro executando o código 900 vezes, uma vez por décimo de grau. Essa abordagem "visual" do Excel foi uma ferramenta que eu criei, que ajudou muito a encontrar a melhor solução para cada parte do código.
Por exemplo, arredondando esse resultado de cálculo específico 13248737,51 para 13248738 ou apenas perdendo os decimais "0,51", quanto isso afetará a precisão do resultado final para todos os 900 testes de ângulos de entrada (00,1 ~ 90,0)?
Consegui manter o animal contido em 32 bits (4 bytes) em todos os cálculos e terminei com a mágica para obter precisão em 23 bits do resultado. Ao verificar os 3 bytes inteiros do resultado, o erro é de ± 1 LSB, excelente.
O usuário pode obter um, dois ou três bytes do resultado para seus próprios requisitos de precisão. Obviamente, se apenas um byte for suficiente, eu recomendaria usar uma única tabela sin de 256 bytes e usar a instrução AVR 'LPM' para obtê-la.
Depois que a sequência do Excel foi executada sem problemas, a tradução final do assembly do AVR para o Excel levou menos de 2 horas; como de costume, você deve pensar mais primeiro, trabalhar menos depois.
Naquela época, eu era capaz de espremer ainda mais e reduzir o uso de registros. O código real (não final) usa cerca de 205 instruções (~ 410 bytes), executa um cálculo sin (x) em média de 212us, com clock de 16MHz. Nessa velocidade, ele pode calcular 4700+ sin (x) por segundo. Não sendo importante, mas pode executar uma onda senoidal precisa de até 4700Hz com 23 bits de precisão e resolução, sem nenhuma tabela de pesquisa.
O algoritmo base é baseado na série de Taylor para sin (x), mas modificou muito para atender às minhas intenções com o microcontrolador AVR e a precisão em mente.
Mesmo que o uso de uma tabela de 2700 bytes (900 entradas * 3 bytes) seja atraente em termos de velocidade, qual é a experiência divertida ou de aprendizado nisso? Obviamente, a abordagem CORDIC também foi considerada, talvez mais tarde, o ponto aqui é espremer Taylor no núcleo do AVR e tirar água de uma rocha seca.
Gostaria de saber se o Arduino "sin (78,9 °)" pode executar o Processing (C ++) com 23 bits de precisão em menos de 212us e o código necessário menor que 205 instruções. Pode ser que o C ++ use CORDIC. Os esboços do Arduino podem importar código de montagem.
Não faz sentido postar o código aqui, mais tarde editarei este post para incluir um link para ele, possivelmente no meu blog neste URL . O blog é principalmente em português.
Esse empreendimento de passatempo sem dinheiro foi interessante, elevando os limites do mecanismo AVR de quase 16MIPS a 16MHz, sem instrução de divisão, multiplicação apenas em 8x8 bits. Permite calcular sin (x), cos (x) [= sin (900-x)] e tan (x) [= sin (x) / sin (900-x)].
Acima de tudo, isso ajudou a manter meu cérebro de 63 anos polido e oleado. Quando os adolescentes dizem que os "idosos" não sabem nada sobre tecnologia, respondo "pense novamente, quem você acha que criou as bases para tudo o que você gosta hoje?".
Felicidades