Aritmética de ponto fixo em microcontroladores

12

Geralmente usamos microcontroladores para fazer as coisas em nossos robôs, mas precisamos fazer alguns cálculos em decimal. O uso de variáveis ​​de ponto flutuante é muito lento, porque uma biblioteca de ponto flutuante de software é incluída automaticamente (a menos que você tenha um microcontrolador de última geração). Portanto, geralmente usamos aritmética de ponto fixo.

Sempre que faço isso, apenas uso um número inteiro e lembro onde fica a casa decimal. No entanto, é preciso algum cuidado para garantir que tudo seja consistente, especialmente quando os cálculos envolvem variáveis ​​em que o ponto decimal está em um local diferente.

Eu implementei uma função atan2 de ponto fixo, mas como estava tentando espremer toda última gota de precisão limitada (16 bits), muitas vezes mudava a definição de onde está o ponto decimal e mudava à medida que o aprimorava. Além disso, eu teria algumas constantes, como uma tabela de consulta quase, que possuem um ponto decimal implícito em algum lugar.

Eu quero saber se existe uma maneira melhor. Existe uma biblioteca ou conjunto de macros que pode simplificar o uso de variáveis ​​de ponto fixo, facilitando a multiplicação e a divisão entre variáveis ​​mistas e permitindo a declaração de números decimais ou expressões constantes, mas convertendo automaticamente para a representação de ponto fixo desejada na compilação Tempo?

ronalchn
fonte
1
Eu acho que isso é melhor para o stackoverflow, pois a solução é genérica e não tem muito a ver com robótica.
precisa
1
@ Jakob - Observe que ambas as perguntas foram encerradas como não construtivas.
Mark Booth
1
Esse é o tipo de coisa que tornaria o C ++ muito útil para sistemas embarcados. Os modelos gerariam o código correto e ideal automaticamente.
Rocketmagnet
1
Posso dar uma olhada na sua função atan? Estou tentando resolver o problema de conversão de ponto flutuante para ponto fixo em minha pesquisa acadêmica e ficaria feliz em resolver o problema.
9788 Joe Hass #
1
Peças @ronalchn de Arduino (um micro AVR) linguagem são implementadas em C ++. Há também uma biblioteca AVR C ++ . E esta discussão sobre qual compiladores usar.
embedded.kyle

Respostas:

7

Seria bom se pudéssemos dizer ao compilador o alcance e a precisão de cada variável de entrada de ponto fixo (talvez dois não possuíssem o ponto de radix no mesmo local), e ele automagicamente - em tempo de compilação - usasse o intervalo correto e operações de precisão e redimensionamento para os valores intermediários e finais em uma série de cálculos. Ouvi rumores de que talvez seja possível fazer isso na linguagem de programação Ada ou nos modelos C ++.

Infelizmente, o mais próximo que eu vi são bibliotecas aritméticas de ponto fixo que exigem que o programador escolha manualmente a representação correta e verifique manualmente se cada operação mantém alcance e precisão adequados. Às vezes, facilitam a multiplicação e a divisão entre variáveis ​​mistas. Tal como:

David Cary
fonte
É quase certamente possível fazer isso usando modelos C ++.
Rocketmagnet
Na verdade, estou trabalhando em algo como o seu comentário "seria bom se ...". É um plug-in para o gcc que converte o código C de ponto flutuante em ponto fixo, otimizando todos os locais de pontos binários ao longo do caminho. Tenho um artigo enviado para um diário da ACM e outro em preparação. Se você tiver código C para a função atan, ficaria feliz em tentar ... Eu poderia devolver o código C que usa variáveis ​​inteiras e faz todo o material de ponto fixo.
9788 Joe Hass #
+1 para uma resposta muito mais completa que a minha. Editei o link no meu para incluir um link para um local para solicitar o código-fonte para abordar o comentário de Mark Booth. Você também pode atualizar seu link. Eu faria isso sozinho, mas uma edição sugerida está na fila e está me bloqueando.
embedded.kyle
1
@Rocketmagnet Certamente é possível implementar pontos fixos usando modelos, consulte FixedPoints (aviso: eu escrevi isso e ainda é muito 'jovem').
Pharap
o link do gcc "a" está quebrado
Lesto 7/03/19
2

Usei a TI IQMath Library para implementar o ponto flutuante virtual em seus DSPs de ponto fixo.

A Texas Instruments TMS320C28x IQmath Library é uma coleção de funções matemáticas altamente otimizadas e de alta precisão para programadores de C / C ++ portarem perfeitamente um algoritmo de ponto flutuante em código de ponto fixo em dispositivos TMS320C28x. Essas rotinas são normalmente usadas em aplicativos em tempo real intensivos em computação, onde a velocidade ideal de execução e a alta precisão são críticas. Ao usar essas rotinas, você pode obter velocidades de execução consideravelmente mais rápidas que o código equivalente escrito na linguagem C padrão ANSI. Além disso, ao fornecer funções de alta precisão prontas para o uso, a biblioteca TI IQmath pode reduzir significativamente o tempo de desenvolvimento de aplicativos DSP.

Isso usa algumas coisas específicas da TI, mas também usei esse código como base para implementar a matemática de ponto flutuante virtual em outros microcontroladores. É preciso um pouco de trabalho para transportar, mas é muito mais fácil do que começar do zero.

embedded.kyle
fonte
@ downvoter Gostaria de comentar o que havia de errado com a minha resposta?
embedded.kyle
+1: esta biblioteca é melhor do que o que ele está usando agora ("use apenas um número inteiro"). Ele não faz tudo o que a pergunta original solicitou, mas acho que uma resposta como essa (útil, mas não uma solução completa) não merece um voto negativo - a menos que exista realmente uma solução completa (o que duvido neste caso )
David Cary
Parece-me que uma resposta que é específica para uma única gama de dispositivos e é apenas gratuita como na cerveja e não na fala é de uso limitado para futuros visitantes.
Mark Booth
@ MarkBooth Alterei o link da biblioteca C28x para a biblioteca C64x. Se você seguir esse link, poderá solicitar o código fonte. Você precisa de um email da empresa ou da universidade para obter acesso. Ainda livre como em cerveja e discurso. Você só precisa levantar a mão e esperar ser chamado antes de poder falar. Um pouco chato, mas depois de ter o código-fonte, ele pode ser adaptado a qualquer processador que você quiser.
embedded.kyle
Obrigado, o código fonte @ embedded.kyle é definitivamente melhor do que apenas o binário, mas ainda de pouco uso geral se a licença permitir apenas que você o use de maneiras limitadas. De acordo com a página C6x Software Libraries , essa fonte é liberada apenas sob a TI Commercial License , que quase certamente não é livre como na fala .
Mark Booth
1

Existem várias implementações (sem bibliotecas que conheço imediatamente) do Binary Scaling (também conhecido como B-scaling)

Nesse caso, você mantém uma nota mental (ou, melhor ainda, documenta o código ...) de onde está o ponto decimal, usando turnos para mover o ponto decimal para cima ou para baixo.

Eu usei o escalonamento B no assembler em projetos de defesa, mesmo nas menores CPUs, para garantir sua adequação a qualquer outra coisa ...

Andrew
fonte
Provavelmente algo assim, mas nunca o vi referido como b-scaling. Penso nele como ponto fixo - o decimal nunca está flutuando, porque mesmo que o ponto decimal pode mudar no decorrer de cálculos, qualquer variável tem sempre o ponto decimal fixo em um determinado local
ronalchn
0

Se você usar um inteiro para lembrar onde o "ponto" é, eles são tipo de usar aritmética de ponto flutuante. Ponto fixo, realmente tem ponto fixo .

atancosπ-π

Isso depende do intervalo de valores que seu aplicativo precisa, mas você pode querer mudar completamente para uma representação de ponto fixo. Ou seja, por exemplo, em vez de manter um número como este:

struct num
{
    uint16_t number;
    uint16_t decimal_point;
};

onde numberestá o número inteiro e decimal_pointdiz onde está o ponto decimal, você pode armazená-lo assim:

struct num
{
    uint16_t integer;
    uint16_t fraction;
};

onde está o número inteiro integer.fraction, que possui o mesmo uso de memória, maior intervalo de valores e, em geral, mais simples de usar.

Shahbaz
fonte
O armazenamento real do ponto decimal o torna mais parecido com um ponto flutuante. Normalmente, o ponto decimal é definido no tempo de compilação e você alterna entre representações, dependendo da sua operação.
26412 Jakob
Eu não quero lembrar como em armazenado em uma variável, quero dizer lembrar como na Lembro-me de como interpretar o resultado (por saber onde o ponto decimal é)
ronalchn
@ronalchn, entendo. Você quis dizer algo como com um #define, certo? Eu pensei que você realmente o armazenasse e isso pode variar de acordo com o tamanho do seu número.
Shahbaz
@ronalchn - você está pensando em B-scaling? (veja minha resposta)
Andrew