domingo, 26 de setembro de 2021

TECNOLOGIA IMITA A NATUREZA

 Aqui em Orlando, atrás da minha casa existe um lago, onde muitos patos “Mallard” o visitam durante o inverno.  Não é à toa que o meu pequeno bairro chama-se “Mallard Cove”.

 As vezes eu fico fascinado com o voo desses pássaros, que me lembram algumas cenas de aviões militares. 
Veja abaixo e compare a semelhança.  Por serem pesados eles são obrigados a voar em velocidade acima dos pássaros comuns, as vezes eles voam acompanhando o asfalto da rua, o fazem em duplinha, debaixo dos galhos das arvores, juro estar vendo manobra militar em alta velocidade.







CAPACITORES

Abaixo um texto coletado sobre capacitores, parte da net, parte traduzida, parte de livros e parte de experiência pessoal.

Foto Wikipedia, Eric Schrader, San Francisco, CA

DEFINIÇÃO:

Rigidez dielétrica : A capacidade do dielétrico para suportar uma certa tensão sem um arco ou a ocorrência de curto-circuito. Quanto maior a força dielétrica, o capacitor suportará maior tensão elétrica.

Absorção dielétrica : Um efeito onde parte da carga armazenada em um capacitor não aparece imediatamente após a descarga, porém vaza lentamente com o passar do tempo. Alguns materiais dielétricos possuem uma espécie de efeito esponja.   É o equivalente à água que mantém a esponja úmida mesmo após você torce-la.  Absorção dielétrica não é uma característica desejável.

Resistência série equivalente (ESR) : Na prática todos os capacitores possuem uma certa resistência em série, devido a fios, materiais, etc.  Baixo ESR é uma característica desejável.

Indutância Série : Na prática capacitores possuem indutância série devido as técnicas de construção utilizadas. A indutância mínima seria o mesmo que um condutor (fio) o mesmo comprimento que o capacitor. Muitas vezes esse valor é muito maior. Com um indutor em série com o capacitor, resulta em um circuito ressonante de série. O capacitor irá ressonar nessa freqüência. Indutância série não é uma característica desejável.  Os capacitores de indutância série mais baixas são usualmente os tipos SMD cerâmicos e tântalo.

Coeficiente de temperatura : Na prática os capacitores variam um pouco o seu valor com a mudança de temperatura. Alguns variam apenas uma pequena quantidade, alguns bastante. O coeficiente de temperatura (mudança na capacitância vs mudança de temperatura) não é sempre linear.

Polaridade : Capacitores que podem ser operados com segurança com apenas uma polaridade DC são chamados capacitores “polarizados”, que podem ser operados sem considerar a polaridade são “não-polarizados”. Às vezes capacitores “polarizados” são combinados de forma especial para permitir uma limitada capacidade de lidar com polaridade reversível, e são chamados de “bipolares”.

Ripple de corrente : A quantidade de corrente AC, que um capacitor pode suportar e quantas vezes ele pode suportar. Nem todos os capacitores são classificados para a corrente de ripple. Esta especificação é aplicada principalmente para capacitores que lidam com correntes AC, ou capacitores de DC com grandes componentes de AC (frequentemente encontrados em fontes de alimentação switching e equipamentos industriais, tais como motor drives etc).


MATERIAIS DIELÉTRICOS :

A maioria dos capacitores são nomeados com base no material usado em seu dielétrico.

Ar : O material dielétrico original. Receptores de rádio de tempo antigo usado variável capacitores feitos de pilhas de placas paralelas com ar entre eles. O ar é um bom dielétrico, que varia ligeiramente com a umidade e partículas em suspensão. Capacitores com dielétricos de ar são impraticáveis para valores para além de algumas centenas de pico farads devido ao seu tamanho crescente. Caps de ar são não polarizados.

Cerâmica monolítica : Materiais cerâmicos fazem um bom dielétrico. Eles podem ser usados para valores de baixas pico farads até geralmente ao redor de um microfarad. Os pequenos valores são geralmente “monolíticos”, eles são feitos de um único dielétrico (geralmente em forma de disco) metal chapeado em ambos os lados do disco, e leads anexados.  Eles também são avaliados pelo coeficiente de temperatura.

COG ou capacitores NPO (zero negativo-positivo) são o mais estável com temperatura, mas geralmente estão disponíveis apenas na gama pico farad. Eles são maiores para determinados valores de capacitância. Há capacitores de coeficiente de temperatura especial para compensação de circuitos. Esses casos são raros.

Capacitores X7R têm um maior coeficiente de temperatura (tempco), mas estão disponíveis em maiores capacitâncias.  Eles são menores em tamanho que NPO. O tempco não não linear e são difíceis de ajusta-los para linearidade, mas os valores variam para mais ou menos alguns poucos percentuais entre 0 a 100 graus Celsius.

Capacitores Z5U dão os maiores valores de capacitância por um menor volume.. O tempco é terrível, muitas vezes caindo para -50% do valor no-20 graus e + 100 graus Celsius (em relação a 25 ° C). Usado apenas para aplicações não-críticas como bypass em fontes de alimentação.

Cerâmica empilhados : Existem capacitores que são fabricados empilhando várias capacitores monolíticos em um único pacote. Eles possuem maior capacitância do que um disco de semelhante classificação. O desempenho ainda está relacionada ao material dielétrico, que poderia possuir um tempco e característica de tensão boa ou ruim.

Cerâmica (em geral) : Para pequenos valores e altas tensões, capacitores de cerâmicas são os melhores.  Eles são geralmente muito baixos na indutância série, e geralmente o ESR não é um problema. Esteja ciente de seus coeficientes de temperatura.  Alguns materiais cerâmicos apresentam alguns efeitos piezelétricos, eles podem ser eletricamente sensíveis a vibrações e choques. A maioria das cerâmicas têm baixa absorção dielétrica. Caps cerâmicos são não polarizados.

Mica : Muito bom, dielétrico muito estável, feito a mica mineral, com placas chapeadas ou depositadas em ambos os lados (muitas vezes prata, daí o nome “prateado mica”).  Desempenham melhor do que as capacitores de cerâmicas na série NPO.  Capacitores de Mica são produzidos para a faixa de pico farads, e a faixa de tensão é para milhares de volts.  Capacitores de mica são não polarizados.

Tântalo : Um dielétrico capaz de produzir  alta capacitância em um espaço muito pequeno. Capacitores de tântalo são feitos de duas construções, úmido e seco. Capacitores de tântalo úmido possuem um eletrólito líquido que forma o dielétrico. Esses foram quase que totalmente substituídos por tântalo seco.   Esses usam um material pó esférico de tântalo com um revestimento dielétrico externa.  Eles são “aglomerados” juntos para formar um material quase contínuo com valor de alta capacitância por unidade de volume. Eles têm indutância série razoavelmente baixa e muito baixo ESR.

AVISO: capacitores de tântalo são RAIVOSAMENTE polares. Invertendo a polaridade DC mesmo por um breve período de tempo fará com que eles ao calor e auto-destruição.  

Capacitores de tântalo são mais comuns em baixas tensões e valores abaixo alguns microfarads. Tensões elevadas e grandes (> 5-10uF) valores os tornam excessivamente custosos.  Seu ESR baixo e indutância série os torna perfeitamente adequados à serviços de bypass de fontes de alimentação. A corrente de fuga é geralmente muito baixa, muito melhor do que os eletrolíticos.  Eles devem ser evitados em circuitos de acoplamento de áudio (região bipolar).

Eletrolítico : Capacitores eletrolíticos possuem esse nome por causa dos produtos químicos usados para formar o dielétrico.  Capacitores eletrolíticos têm placas enroladas com uma longa e fina tira de papel alumínio.  O dielétrico é um fino (vários átomos densamente) revestimento de óxido de alumínio (um excelente isolante).  O óxido de alumínio é formado por uma reação química entre o eletrólito e o alumínio, na presença de um campo elétrico. Este dielétrico formado dá os capacitores algumas únicas vantagens e desvantagens. 

Capacitores eletrolíticos podem ter grandes capacidades por espaço de unidade, uma vez que o dielétrico é muito fino. O dielétrico pode ser adaptado para suportar tensões até cerca de 450 VCC, o limite superior para caps eletrolíticos. As desvantagens do eletrolítico vêm do eletrólito, e como o dielétrico é formado. O eletrólito irá secar no tempo, fazendo com que os capacitores para gradualmente diminuir a capacitância.  Usar o capacitor além suas classificações (tensão, polaridade ou corrente de ripple) vai aumentar a pressão interna no capacitor até que libere a pressão (vent)  e perde eletrólitos  ou explode. 

O outro problema é que, se o capacitor eletrolítico não é usado por um longo tempo, o dielétrico se torna mais fino, diminuindo a tensão que ele pode suportar. O dielétrico precisa de um campo elétrico (carga) a fim de manter a sua força. Eletrolíticos armazenados sem uso (em armazenamento ou em equipamentos não utilizados) podem ter suas camadas dielétricas restauradas aplicando lentamente o aumento dos níveis de tensão DC, o procedimento pode levar dias. 

Eletrolíticos sofrem de envelhecimento acelerado em temperaturas elevadas. Uma regra é que sua vida é cortada ao meio para cada aumento de 100° Celsius acima do ambiente (25° C). Por todas estas razões, eletrolíticos têm vida limitada e o usuário pode esperar para substituí-los em algum momento no futuro. 

Excessivo ruido de 60Hz (humm) em uma fonte de alimentação ou imagens de rolamento instável em um monitor são frequentemente sinais de um eletrolítico chegando ao fim da sua vida útil. Capacitores eletrolíticos têm uma quantidade substancial de escapamento e absorção dielétrica. Isso pode ser um problema em circuitos de temporização e muitas vezes limita a sua utilização. 

Alguns projetos (como o temporizador 555) minimizam essas falhas, usando o capacitor em tensões de funcionamento onde esse fator aparece de forma mínima. A estabilidade de temperatura de eletrolíticos é pobre e raramente especificado.

Eletrolíticos polarizados : A forma mais comum de capacitores eletrolíticos. Estes estão disponíveis nos tamanhos acima de 1 uF até Farads, e disponíveis a suportar tensões de 5 a 450 Vcc.  Existem tipos especiais que trabalham em faixa extendida de desempenho, geralmente especificado para temperaturas mais altas, maior corrente de ripple, baixa ESR e maior confiabilidade. Todas estas classificações geralmente resultam em um componente fisicamente maior.  Existem eletrolíticos “selados” para aplicações em temporização, mas eles são raros.

Eletrolíticos bi-polar : Estas são uma variedade especial de capacitor eletrolítico que são usados em aplicativos que misturaram polaridade, tais como o acoplamento de aplicações de áudio. Fisicamente, eles são feitos de dois eletrolíticos polares ligados em série nos seus terminais negativos. Eles são geralmente duas vezes tão grandes quanto um eletrolítico polarizado para o mesmo valor de tensão e capacitância. Usos comuns em Crossovers econômicos em alto-falantes.

Supercaps (bateria) : Estas são capacitores eletrolíticos que são especializados para os tempos de descarga longa com cargas de corrente muito baixas. Eles são usados por aplicativos de backup de memória no lugar de baterias Ni-Cad ou lítio.

O uso principal para capacitores eletrolíticos é para alimentação, filtragem e bypass. Usos menores são para acoplamento em operação unipolar de áudio (onde um terminal é sempre mais positivo do que o outro) ou aplicações não-críticas de cronometragens.

Capacitores de filme : Capacitores de filme são os membros mais incompreendidos da família de capacitores.  Eles são nomeados após o material usado como o dielétrico. Eles vêm em duas variedades de físicas, a construção de Filme e Película, ou construção de Filme Metalizado.  Eles estão disponíveis em valores em torno de .0005 uF (500 pF) para vários microfarads e tensões de em torno de 10 VDC a vários milhares de VCC.   

Existem capacitores de filme para aplicações especiais podem ir até vários milhares de microfarads, nesse caso possuem maior tamanho e preço. A maioria das capacitores de filme tem ótima estabilidade em variações de temperatura, e com baixa absorção dielétrica. Por via de regra são capacitores não polarizados e têm boa resposta de AC.  Indutância série varia de baixo a alto, dependendo da geometria da construção. Em sua forma mais simples, eles são construídos de duas peças de alumínio, separadas por um “filme” do material dielétrico. Isso é chamado de construção de filme e papel alumínio e é o maior e mais robusto na maioria dos casos. Alguns capacitores de filme têm uma camada de metalização, geralmente de alumínio, depositada em ambos os lados do filme. Isso é chamado de película metalizada e é geralmente menor e mais caro. Ambos os tipos têm desempenho semelhante.  A seguir alguns tipos conhecidos.

Filme de poliéster (Mylar) : O material dielétrico mais comum em uso. É de baixo custo e os tipos existentes são em filme e papel alumínio metalizado.  As faixas de tensões suportadas vai de 50 VDC Mylar 200 VDC (até 1000 VDC).  Mylar sofre absorção dielétrica (0.2%), que o torna inadequado para aplicações tais como capacitores de temporização de VCO e aplicativos de Sample and Hold. Capacitores de poliéster não tem um coeficiente de temperatura linear, sua capacitância aumenta em alta temperatura e diminui em baixas.  A forma geral da curva é semelhante a uma letra horizontal “S”. Entre 25~85° Celsius têm um coeficiente de temperatura crescente. Eles são úteis para áudio, acoplamento, circuitos de temporização semi-critical, controles de tom, usos gerais. Faixa de temperatura é de 125° Celsius.

Filme de poliestireno : Santo Graal dos capacitores de filme, poliestireno tem as características elétricas mais desejáveis. Com coeficientes de temperatura tão baixos quanto 30~40 ppm (especial) e normalmente inferior a 120 ppm (standard), eles têm excelente linearidade de coeficiente de temperatura na faixa de temperatura que qualquer equipamento já trabalhou nesse planeta. Absorção dielétrica (. 02%) é o mais baixo encontrado em qualquer variedade de capacitor. Isto faz a escolha de capacitores de poliestireno o primeiro para todos os circuitos de tempo crítico, tais como clocks de VCO e FCR e todos os os circuitos de Sample/Hold. Capacitores de poliestireno não toleram temperaturas altas (máximo de 85 graus Celsius), portanto eles não estão disponíveis na forma metalizado. Descuido ao soldar podem destrui-los facilmente, e em muitos casos não são adequados à produção automatizada. Há um rumor persistente que o único fabricante no mundo que continuava a produzir capacitores de filme de poliestireno cessou a produção. Ainda há estoque no mercado, mas as pessoas também são aconselhadas a armazena-los por garantia. Há alguns novos capacitores de policarbonato que se aproximam do desempenho de poliestireno.

Filme de polipropileno : Capacitores de polipropileno são usados no lugar de poliestireno. Ligeiramente maior do que o poliéster (Mylar), são eletricamente superiores e um pouco maior em tamanho. Eles têm um coeficiente de temperatura linear, negativa de-150 ppm (e especial-250 ppm para compensação de bobinas em aplicações de filtro). Se o coeficiente de temperatura negativo é desejável, eles são usados no lugar de poliestireno. Absorção dielétrica é 0.02% e a escala de temperatura é de até 105° Celsius no máximo.

Película do policarbonato : Capacitores de policarbonato são outra boa opção para substituição de poliestireno. O tempco e estabilidade de temperatura não são tão bons como poliestireno. São lineares em uma faixa limitada de temperatura (25-85° Celsius). Além desse intervalo não são lineares (semelhante a capacitores de poliéster).  Capacitores de policarbonato suportam temperaturas muito mais altas (máximo de 125° Celsius) do que o poliestireno, então podem ser construídos com película metalizada.  As gamas de tensão chegam a alguns milhares de volts. Estas capacitores são mais adequadas para aplicações de sincronismo e acoplamento crítico e podem ser usados sempre que o poliestireno é a escolha preferida, com uma ligeira diminuição no desempenho. Capacitores de policarbonato têm uma quantidade moderada de sensibilidade de umidade e absorção dielétrica é em torno de 0.08%. Capacitores de policarbonato são cerca de 12% maior do que o poliéster (Mylar).

Filme polysulfone : As mesmas especificações como policarbonato, mas com as classificações de temperatura ainda maiores. Estes são usados onde o desempenho de alta temperatura é obrigatório (máx. 150 graus Celsius) e raramente são usados para aplicações gerais. Eles têm um coeficiente de temperatura razoavelmente linear de 25° Celsius e acima, mas que cai ligeiramente a baixas temperaturas. Capacitores de Polysulfone possuem uma pequena sensibilidade a umidade e absorção dielétrica é em torno de 0.08%.

Filme de Teflon : Teflon trabalha bem como poliestireno e é bom também para altas temperaturas. Eles são duas vezes o tamanho de um capacitor de poliéster (Mylar), e o preço elevado torna sua utilização incomum para todos, e servem mais apropriadamente para aplicativos mais essenciais (leia aeroespacial). A dificuldade em fazer qualquer coisa a aderir ao filme faz a metalização impraticável. Teflon é impermeável à umidade e tem absorção dielétrica ao redor de 0.02%.

sábado, 25 de setembro de 2021

CORDIC - SIMPLES e FÁCIL

 CORDIC -  ESSE TIGRE NÃO MORDE

CORDIC é um procedimento usado para determinar e calcular valores como seno(x), coseno(x), logarítmo(x), tangente(x) e outros, sem usar multiplicação ou divisão, nem formulas malucas ou tabelas gigantes.  

CORDIC é usado em muitas calculadoras e até programas de computador, onde velocidade é importante, mas sem requerer muito hardware para tais cálculos.   

A criação do CORDIC teve por base exatamente isso, velocidade e facilidade, e acabou sendo tão simples, que até mesmo soluções mecânicas foram inventadas para tal.

Pois é, depois de anos com medo desse bicho, fui atrás e cutuquei com vara curta.
Pensei comigo mesmo que já era hora de ao menos entender como funciona nos detalhes.

Ao ler os textos na Internet, me apavorei ainda mais, o povo usa formulas complexas, e desenhos que confundem mais do que explicam.   Mas não desisti, pois sempre pensei, "como pode algo simples ser tão complexo e com descrição tão assustadora?".

Devagar e ao meu tempo fui entendendo e montando um racional mais simples de explicar como o CORDIC funciona, de forma a poder escrever um programa para o microcontrolador AVR em assembly.   Para quem conhece assembly, é claro que você precisa entender muito bem e em detalhes o que está fazendo, portanto, quando eu decidi escrever CORDIC para o AVR em assembly, é porque eu já tinha entendido tal procedimento muito bem.  Descobri que CORDIC não morde, na verdade é até manso demais.

No passado escrevi uma rotina, também em AVR assembly, para calcular o valor de seno(x) e coseno(x), considerando o ângulo com uma casa decimal, de zero a 90 graus (0 ~ 89.9°), usando o sistema de aproximação de Taylor que usa uma pancada de fator de potência e divisões por fatoriais.  Foi complicado e demorou.  Agora gostaria de comparar a performance daquela rotina contra o CORDIC, e por isso meti as caras no programa.

Primeiro, CORDIC faz uma mágica com uma tabela pequena, de no máximo 22 ou 23 entradas.  Essa tabela contém os valores de ângulos entre zero e 45°.  Inicia em 45° e vai decrementando até chegar a valor muito pequeno, a última entrada é 0.00005464°.   Quase tudo em linguagem de programação usa divisão binária, por dois, mas não nessa tabela.  Abaixo os primeiros 10 elementos da tabela;

45.000000
26.565051
14.036243
 7.125016
 3.576334
 1.789911
 0.895174
 0.447614
 0.223811
 0.111906
...

Esses valores de ângulos são calculados antecipadamente no Excel ou calculadora e digitados no programa, eles representam o ângulo cuja tangente é 1, e dividida por dois consecutivamente.  Ou seja, a atan(1/2^n) onde n vai de zero a o valor máximo de elementos na tabela.  Os valores foram calculados com base em:

atan(1/1)   ==>  atan(1)
atan(1/2)        atan(0.5)
atan(1/4)        atan(0.25)
atan(1/8)        atan(0.125)
atan(1/16)       atan(0.0625)
... 

Note que a divisão por dois não é do ângulo, mas da tangente, e a tabela mostra os angulos que representam essa tangente sendo divida por dois.   Isso é fundamental para entender CORIC.   Então a tabela contém os ângulos que representam a divisão binária do valor da tangente entre 45° e praticamente zero.

Mas o que a tangente tem a ver com isso?
Lembrar algumas propriedades de trigonometria:
Sin(x)^2 + Cos(x)^2 = 1
Por exemplo, Sin(30) = 0.5, Cos(30) = 0.866,  0.5^2 = 0.25, 0.866^2 = 0.75, somando ambos = 1.
O mais importante aqui, a Tangente = Seno(x) / Coseno(x).
Então, sabendo a tangente e o ângulo, já é meio caminho andado para saber o seno(x) e coseno(x).

Mas como saber a tangente se só se tem o ângulo?
Aha, ai é que entra a tabela.
Mas a tabela só tem poucos valores de ângulo que corresponde à tangente.
Ai é que entra a mágica o número K, que é conhecido como "ganho do CORDIC".

Multiplicando todos os cosenos dos ângulos da tabela, ou seja, cos(45) * cos(26,56505) * cos(14.03624)... ter/a
um valor de 0.6072529350088810... e quanto mais preciso esse numero, mais precisos serão os valores obtidos de seno(x) e coseno(x) pelo algoritmo CORDIC.    Esse valor ai acima será sempre o mesmo, nem precisa mais calcular, pode usa-lo sem medo.  CORDIC Gain.  Na internet você fica louco tentando entender o que significa esse CORDIC Gain, o povo complica demais a explicação.  Só como fato curioso, o ângulo cujo coseno é 0.6072... é 52.60886...°, e a princípio não tem nada a ver com coisa alguma, mas é isso mesmo.

Já estamos chegando na mágica.  Veja que existe uma relação entre os valores da tabela, que são os ângulos correspondentes a tangente de 45° que é "1.00", e tangentes sendo divididas binariamente por dois, e agora os cosenos dos ângulos da tabela multiplicados um pelo outro, obtendo 0.6072...   Estamos preparando uma divisão binária entre ângulos, tangentes e cosenos.  A mágica.

O algoritmo CORDIC inicia com duas variáveis, uma de seno e outra de coseno, que chamaremos de Y e X.  A variável de seno (Y) é iniciada com zero.  A do coseno (X) é iniciada com o valor 0.6072...  Também teremos duas outras variáveis, a do ângulo de entrada (o que o usuário entrou para buscar o seno e coseno), e a do ângulo-de-busca.  Vamos dar nomes, a do ângulo de entrada, chamaremos de ANGENTRADA, e a do ângulo de busca, de ANGBUSCA.   A ANGENTRADA será iniciada com o ângulo do usuário, a ANGBUSCA com zero.   Também um ponteiro apontando para o início da tabela, onde terá 45° como primeiro elemento.  Outras duas variáveis de nome YS e XS, que recebem os valores de Y e X (atuais) shiftados à direita (divididos por dois), a cada rodada da rotina

Pronto, o CORDIC está pronto para rodar e é muito simples.
O que ele faz é um joguinho de ping-pong e uma busca binária.

Inicia verificando se o ANGBUSCA é maior ou menor que ANGENTRADA. Inicialmente ANGBUSCA é zero, portanto será menor.  

Quando MENOR, ele SOMARÁ o angulo apontado na tabela na variável ANGE, e também somará o XS em Y, e subtrairá YS de X.

Quando ANGBUSCA for MAIOR que ANGE, a coisa é ao contrário, ele SUBTRAIRÁ o angulo apontado na tabela na variável ANGE, agora SUBTRAIRÁ XS de Y, e SOMARÁ YS em X.

Se você entendeu isso, entendeu CORDIC.

Ele fará de 14 a 21 loops, de acordo com o que você quer de precisão e elementos na tabela.
A cada LOOP ele incrementa o ponteiro na tabela, apontando para um ângulo menor e menor, e usa esse ângulo menor para ser somado ou subtraido da variável ANGBUSCA, a fim de fazer um tipo de perseguição, buscando fazer essa variável ANGBUSCA ter o conteúdo mais próximo possível da ANGENTRADA.  Como os valores na tabela são o resultado de uma divisão binária da Tangente, é óbvio que com o mesmo número de divisões na busca, a variável ANGEBUSCA terá um valor muuuito próximo da ANGENTRADA, com diferença muito pequena. 

Também, a cada loop, conforme ANGEBUSCA seja menor ou maior, terá o valorzinho da tabela sendo somado ou subtraído à essa variável, e o valor de XS e YS será somado ou subtraído de Y e X. 

Mas veja que X iniciou com o CORDIC Gain 0.60725... e isso é a multiplicação de todos os cosenos dos ângulos da tabela.  Como o valor atual de X e Y em cada passada é shiftado para a direita, tantos bits quanto for o numero da passada, esse valor de X e Y representam o valor do coseno do angulo cujo valor da tangente foi também dividida binariamente.   O que ele faz ao subtrair ou adicionar o XS e YX em Y e X (veja que é cruzado), é exatamente mantendo a relação entre seno e coseno também buscando ficar o mais próximo possível de ANGBUSCA.  Quando seno sobe, coseno desce e vice-versa. 

A mágica é muito boa.  Confuso? olhe o código ao final e entenderá.

Ao completar as "n" passadas, o valor em X e Y corresponderão ao coseno e seno do angulo na variável ANGENTRADA, com resolução e precisão.   Rodando 14 passadas já é suficiente para ter uma boa precisão, mas quanto mais passadas melhor.  A quantidade de passadas também depende da escala do CORDIC Gain, usando 0.6072 x 65536 (16 bits) esse valor vai chegar a zero já após 14 ou 15 passadas, não adianta continuar fazendo passadas, com esse valor já zerado (XS e YS), nada será adicionado ou subtraído das variáveis X e Y, então para ter mais passadas, o CORDIC Gain terá que usar mais de 16 bits, para pelo menos 8 dígitos decimais de precisão será necessário usar 3 bytes (24 bits) no CORDIC Gain (e inicial em X).   

Notar que, a quantidade de bits (multiplicador do CORDIC Gain) nada tem a ver com o multiplicador do angulo de entrada, nem da tabela de ângulos, esses dois tem que usar o mesmo multiplicador, mas 14 bits é suficiente (multiplicar o angulo de entrada e a tabela por 16384, por exemplo).

Mas é claro que, num microcontrolador você não trabalha com números tão pequenos, querendo trabalhar com números inteiros.  Então tudo, desde a tabela, quanto ao CORDIC Gain, você já multiplica por 65536 para ter dois bytes inteiros a brincar.  Eu já usei 3 bytes e multipliquei logo por 2^24.

Parte lógica do código, todas as variáveis são integers e unsigned, mas ocorre um probleminha de valor negativo se a ENGENTRADA for menor de 4.8... ou maior de 85.2... (algo assim), mas é facilmente resolvível usando 3 bytes nas variáveis X e Y e quando shiftar XS e YS abaixo, o primeiro shift ser aritmético, ou seja, copiar o bit de alta ordem para os bits sendo inicialmente empurrados para a direita, assim, se o valor de X ou Y ficarem negativos, o valor dividido por SHIFTS (shift right) também será negativo, e a soma ou subtração se encarrega de resolver esse negativo mesmo usando números inteiros unsigned.  Assembly é lindo.  O mundo todo usa variáveis signed para o CORDIC, exatamente por esse problema dos ângulos pequenos, eu resolvi isso somando 5 graus no ANGENTRADA e também inserindo 5 * 65536 em X no início, e usando o artifício do aritmetic shift right em XS e YS mantendo o bit de mais alta ordem significando o sinal shiftado, pronto, resolvido.   Se X = FF0224, o bit de alta ordem me diz que ele é negativo, pois nenhum valor positivo chegará a ser tão alto em 3 bytes (por mais que seja 90°x65536 será 5A0000, bit de alta ordem será sempre zero para positivos). Ao usar ASR para shiftar para a direita, ficará FF8112, mantendo a informação negativa, e ao somar, ou subtrair (de Y) resolverá sozinho.  Se não usasse ASR, após o shift seria 7F8112, o que seria considerado um valor positivo na soma ou subtração e causaria problemas.

Abaixo o bicho gigante, cabeludo, cheio de dentes e unhas, o famoso CORDIC para calcular seno e coseno.
Ah sim, usando o Mult = 65536, o valor resultando de seno e coseno em Y e X também estará entre 0 e 65536, ou seja, é só considerar o ponto decimal em frente ao número obtido.   Se ANGENTRADA for 30, a variável Y terminará com o valor 32768, que significa 0.5 (metade) de 65536.

Depois dê uma olhadinha nos outros websites da Internet explicando CORDIC e veja como lá o bicho é pintado de cabeludo, como por exemplo esses: 
ou até mesmo na Wikipedia (que deveria ser simples):  https://en.wikipedia.org/wiki/CORDIC

Código simples em Basic para entender:

Mult = 65535
Tab(1)  = 45 * Mult
Tab(2)  = 26.56505  * Mult
Tab(3)  = 14.03624  * Mult
Tab(4)  = 7.125016  * Mult
Tab(5)  = 3.576334  * Mult
Tab(6)  = 1.789911  * Mult
Tab(7)  = 0.895174  * Mult
Tab(8)  = 0.4476142 * Mult
Tab(9)  = 0.2238105 * Mult
Tab(10) = 0.1119057 * Mult
Tab(11) = 0.0559529 * Mult
Tab(12) = 0.0279765 * Mult
Tab(13) = 0.0139822 * Mult
Tab(14) = 0.0069941 * Mult
Tab(15) = 0.0034971 * Mult
Tab(16) = 0.0017485 * Mult
Tab(17) = 0.0008743 * Mult
Tab(18) = 0.0004371 * Mult
Tab(19) = 0.0002186 * Mult
Tab(20) = 0.0001093 * Mult
X = 0.60725293 * Mult
Y = 0
ANGBUSCA = 0
ANGENTRADA = 30 ; entrada do usuário
XS = 0
YS = 0
SHIFTS = 0

LOOP:

  FOR L = 1 to 20
    YS = Y / SHIFTS
    XS = X / SHIFTS
    
    IF ANGENTRADA > ANGBUSCA THEN
       X = X - YE
       Y = Y + XE
       ANGBUSCA = ANGBUSCA + TAB(L)
    ELSE
       X = X + YE
       Y = Y - XE
       ANGBUSCA = ANGBUSCA - TAB(L)
    END IF

    SHIFTS = SHIFTS * 2   
  NEXT L


Vamos fazer um exercício prático, e multiplicando tudo por 65536 para ter inteiros.
Angulo de entrada = 30° * 65536 = 1966080
CORDIC Gain = 0.607252... x 65536 = 39797
Angulos somados ou subtraídos de AngBusca abaixo, são os valores da tabela x 65536.
Novamente, na lista abaixo, a cada passo XS = X/2^passo e YS = Y/2^passo
Vermelho AngBusca = AngBusca + Tabela, Y = Y + Xs,  X = X - YS 
Azul AngBusca = AngBusca - Tabela,  Y = Y - XS,  X = X + YS
 

AngEntrada  AngBusca       X      Y     XS     YS
  1966080          0   39797      0  39797      0    Passo 0
  1966080    2949120   39797  39797  19899  19899    Passo 1
  1966080    1208153   59696  19898  14924   4975    Passo 2
  1966080    2128032   54721  34822   6840   4353    Passo 3
  1966080    1661087   59074  27982   3692   1749    Passo 4
  1966080    1895466   57325  31674   1792    990    Passo 5
  1966080    2012770   56335  33466    880    523    Passo 6
  1966080    1954104   56858  32586    444    255    Passo 7
  1966080    1983439   56603  33030    221    129    Passo 8
  1966080    1968771   56732  32809    111     64    Passo 9
  1966080    1951437   56796  32698     56     32    Passo 10
  1966080    1965104   56764  32754     28     16    Passo 11
  1966080    1966937   56748  32782     14      8    Passo 12
  1966080    1966020   56756  32768      7      4    Passo 13
  1966080    1966478   56752  32775      4      2    Passo 14
  1966080    1966249   56754  32771      2      1    Passo 15
  1966080    1966134   56755  32769      1      1    Passo 16
  1966080    1966077   56756  32768      0      0    Passo 17

Valor Final Y = Sin(30) = 32768 / 65536 = 0.5
Valor Final X = Cos(30) = 56756 / 65536 = 0.866027...

Coincidentemente os valores corretos já foram obtidos no passo 13, mas é impossível dizer que eram corretos antes de usar toda a tabela e também o ANGBUSCA estava com 40 de diferença do ANGENTRADA.

Esse mecanismo do CORDIC pode ser usado (com outros valores de tabela e Gain) para calcular logaritmos, e outros.   Pense como você faria a tabela para calcular números elevados a potência, ou raiz quadrada.

Fato também interessante, é que o algoritmo CORDIC acima, tanto funciona em Graus como em Radianos, basta que a tabela seja gerada na escolha, e o angulo de entrada também.

Mais tarde posto aqui o código assembly do AVR para calcular sin(x) cos(x).


OTIMIZANDO O ALGORITMO CORDIC ORIGINAL

Preparando e já otimizando o CORDIC original, para implementar em AVR Assembly, existem alguns detalhes que já podemos ir mudando, para acelerar o processo.   Inicialmente vejo 3 possíveis melhorias.

OTIMIZAÇÃO #1

Por exemplo, observe que o ANGBUSCA inicia com zero, e obviamente ele será SEMPRE menor que o ANGENTRADA no primeiro passo.  Então, por que não eliminar o "Passo 0" e "Passo 1", se já sabemos o que irá acontecer?  Essa alteração economizaria em torno de 5~6% do tempo total.

Veja a linha do "Passo 1", ANGBUSCA vai receber 45°, o primeiro ítem da Tabela, aqui no caso multiplicado por 65536 = 2949120.  Também, veja que quando ANGBUSCA é menor que ANGENTRADA e soma valor da tabela no ANGBUSCA, também soma o valor de X em Y e já prepara XS e YS com a metade de X e de Y, para somar ou subtrair em Y e X, conforme se ANGBUSCA ficar maior ou menor que ANGENTRADA no "Passo 2".

Então, o normal é X receber o valor de CORDIG GAIN, aqui no caso 39797 e Y receberia zero, mas como estamos eliminando o "Passo 0", já colocamos CORDIG GAIN também em Y.

Então, para eliminar o "Passo 0", faremos X = Y = 39797, ANGBUSCA = 2949120, XS = YS = 19899, e já partimos para o "Passo 2".

OTIMIZAÇÃO #2

Outra melhoria a ser feita, que funciona bem em Assembly, é evitar comparar ANGENTRADA com ANGBUSCA a cada passo, isso requer 4 instruções, 3 para comparar os registradores que compõe ANGBUSCA com ANGENTRADA e a instrução de salto condicional.  Podemos então no início carregar as variáveis ANGENTRADA com zero e ANGBUSCA com o valor do ângulo de entrada, porém negativo.  Ou seja, se o angulo a calcular o sin() for 30°, vezes 65536 =  1966080 (0x1E0000) o negativo é 0xE20000, a carregar no ANGBUSCA.  Motivo dessa mudança?  Ao somar os valores da Tabela a cada passada, se o resultado da soma for valor positivo, significa que ANGBUSCA acabou maior que ANGENTRADA (que é zero), se ficar negativo significa que ficou MENOR que ANGENTRADA.   Então, não precisa comparar os 3 bytes e decidir, basta olhar o bit de mais alta ordem do byte de mais alta ordem do ANGBUSCA (no caso acima, 0xE2 = 0b11110010, se estiver levantado, é porque o valor é negativo, então ANGBUSCA é menor que ANGENTRADA, e vice-versa.   Também podemos observar o C (carry) bit da soma ou subtração do byte de mais alta ordem (igual ao bit 7 desse byte) A decisão seria só por verificar um bit.  No AVR existe a instrução Skip if Bit in Register is Cleared/Set (SBRC, SBRS), seria só uma instrução ao invés de quatro, vezes a quantidade de passos.   Se usarmos 21 passos, seriam 63 instruções de economia, se rodando a 8MHz economizaríamos 7.8 microsegundos, isso é quase 6% to tempo total.

Ou seja, nesse jogo de somar e subtrair valores da Tabela no registrador ANGBUSCA, o programa estaria tentando manter ANGBUSCA mais próximo possível de zero.  

Você pode se perguntar, qual é a grande vantagem de fazer tudo isso só para economizar 15~20 microsegundos?  Veja, quando escrevendo código em assembly, você busca excelência, rapidez, menor tamanho, facilidade de compreensão da rotina, extremamente funcional, preciso e livre de erros.   Se não estiver preocupado com isso, escreva em linguagem de alto nível, como C, e use bibliotecas prontas, e aceite o resultado que for.

OTIMIZAÇÃO #3

O algoritmo tradicional CORDIC compara ANGENTRADA com ANGBUSCA e decide se soma ou subtrai o próximo valor da tabela em ANGBUSCA, e se soma e subtrai valores XS e YS de Y e X, veja abaixo:

SHIFTS = 0
FOR L = 1 to 20
    YS = Y / SHIFTS
    XS = X / SHIFTS
    IF ANGENTRADA > ANGBUSCA THEN
       X = X - YE
       Y = Y + XE
       ANGBUSCA = ANGBUSCA + TAB(L)
    ELSE
       X = X + YE
       Y = Y - XE
       ANGBUSCA = ANGBUSCA - TAB(L)
    END IF
    SHIFTS = SHIFTS * 2   
  NEXT L

Também observe acima que a cada passo, XS e YS é o resultado de X e Y deslocado para a direita 2^(L-1) vezes, a variável SHIFTS acima representa isso.   Veja na lista de resultados, passos 8 a 12 abaixo, observe passo 10, X = 56796 (0xDDDC) será deslocado 10 bits para a direita para gerar XS = 56  (0x38).  Também veja que no espaço entre XS = 55.5 a 56.49, cujo inteiro é 56, ao elevar esses décimos 2^10, ou exatamente a variação 1 x 2^10, teremos uma possível variação em X de 1024.  Isso significa que não importa se o valor 64 de YS (YE no loop acima) no passo 9 seja somado ou subtraído de X, que não vai mudar o valor em XS.  Ou seja, é garantido que, do passo 10 até o final o valor exato de YS somado ou subtraído de X não irá interferir mais em XS, então a partir desse passo basta deslocar o valor anterior de XS e YS um bit à direita a cada passo.

O resumo disso é que a partir do passo 10 (metade dos passos) já não é mais necessário deslocar X e Y (passos-1) à direita para obter YS e XS, será só perda de tempo e ciclos de clock.  A maneira fácil de verificar qual passo é o limite, é verificar se 2^(passo-1) é maior ou menor que XS na tabela de resultados.  Como no exemplo foram usados 16 ou 17 passos, veja que 2^8 = 256 e é maior que 221  (XS no passo 8), mas 2^7 (128) é menor que XS 444 no passo 7, portanto já a partir do passo 8 já faz sentido aplicar só um deslocamento à direita dos XS e YS anteriores para os novos XS e YS e economizar ciclos de clock.  Perceba que o valor 8 é metade do numero de passos.  Se usando 22 passos, já a partir do passo 11 é possível usar essa otimização. 

Como a quantidade de deslocamentos dos bits de XS e YS variam de acordo com o número do passo, e como essa otimização é usada da metade mais alta de passos, estaríamos economizando a maior parte dos deslocamentos.   Como XS e YS no exemplo usam 16 bits, são dois deslocamentos e o loop do número de passos, então, do passo 8 até o 16 seriam 8+9+10+11+12+13+14+15+16 = 108 deslocamentos em 2 bytes + um contador + jump relativo a cada passo, a transferência de X para XS e Y para YS antes dos deslocamentos, a economia seria em torno de 6 clock cycles por deslocamento, em torno de 650 clock cycles, em 8MHz significa ~81 microsegundos.  Porém agora teríamos deslocamento simples de 2 bytes x 8 = 16 ciclos de clock adicionais, economia final em torno de ~78 microsegundos.  Essa economia significa em torno de 48% do tempo total, somado com os 5 e 6% das otimizações anteriores, estaríamos chegando a uma redução de ~58% da rotina original do CORDIC.

Em assembly, nos passos acima de 8 já podemos simplesmente mover Byte2 para Byte3 e Byte1 para Byte2, ao invés de fazer 8 deslocamentos entre os 3 bytes, isso já reduz um bom percentual de ciclos de clock no processo, mas a otimização #3 reduz bem mais.

                         X      Y      XS     YS
  1966080    1954104   56858  32586    444    255    Passo 7
  1966080    1983439   56603  33030    221    129    Passo 8
  1966080    1968771   56732  32809    111     64    Passo 9
  1966080    1951437   56796  32698     56     32    Passo 10
  1966080    1965104   56764  32754     28     16    Passo 11
  1966080    1966937   56748  32782     14      8    Passo 12

Resumo das otimizações 1, 2 e 3:  

Eliminar passo 0 e 1, carregando os registradores com valores já conhecidos a acontecer.

Mudar a forma de comparar se o ANGBUSCA é maior ou menor que ANGENTRADA, fazendo ANGBUSCA = ANGENTRADA  (negativo) e zerando ANGENTRADA, e só observando o bit de alta ordem de ANGBUSCA para decidir se usa as instruções em azul ou vermelho da rotina.

    IF ANGENTRADA > ANGBUSCA THEN
       X = X - YE
       Y = Y + XE
       ANGBUSCA = ANGBUSCA + TAB(L)
    ELSE
       X = X + YE
       Y = Y - XE
       ANGBUSCA = ANGBUSCA - TAB(L)
    END IF

E por fim, eliminar os deslocamentos de X e Y para XS e YS 2^(passo-1) a partir da metade dos passos até o fim, fazendo só um simples shift-right do valor anterior de YS e XS.