Há algum tempo venho pensado numa forma de transmitir um variável tipo float do PC para o arduino, com o menor número de bytes possível, e alguns da comunidade tem tido interesse em gravar na EEPROM do arduino um float. Cheguei a uma conclusão e queria compartilhar com os colegas.

Nesse texto mostrarei como usar essa estratégia para escrever na EEPROM do arduino um float de valor qualquer, e fazer a leitura.

Criei a seguinte função para escrita:

int escrita(float num,int endereco){

  float *Pnum;

  char *pont;

  Pnum = # 

  pont = (char*)Pnum;

  int j = 0;

  for(int i = endereco; i<=endereco + 3; i++)

  {

    EEPROM.write(i,*(pont + j));

  }

  return (endereco + 4);

}

Essa função tem dois argumentos óbvios, o float a ser gravado e o endereço.

Só que na EEPROM só se pode gravar um byte de cada vez, assim como na comunicação serial, só se pode transmitir um byte de cada vez, Porém um float é representado por 4 bytes, o que fazer?

Que tal “quebrar” ou dividir o float em nível de bytes. É isso que a função faz.

Primeiro é declarado um ponteiro do tipo float que vai receber o endereço que corresponde aos 4 bytes da variável num.Se esse ponteiro for incrementado ele irá avançar 4 bytes.

Mas se for usado um cast (char*) e o resultado atribuído a outro ponteiro desta vez um do tipo char (1 byte), no caso com nome pont, o incremento deste ponteiro irá apontar para o segundo byte de num.

pont = endereço do 1º byte.

pont+1 = endereço do 2º byte.

pont +2 = endereço do 3º byte.

pont+3 = endereço do 4º byte.

Como o que nos interessa é o valor então:

*pont = valor do 1º byte.

*(pont+1) = valor do 2º byte.

*(pont +2) = valor do 3º byte.

*(pont+3) = valor do 4º byte.

Então seguindo essa ideia é usado o um laço for para gravar byte a byte na EEPROM.

A função retorna o próximo endereço livre.

float leitura(int endereco)

{

  float num2 = 0; 

  float *Pnum2;

  char *pont2;

  Pnum2 = &num2;

  pont2 = (char*)Pnum2;

  int j = 0;

  for(int i = endereco; i<=endereco + 3; i++)

  {   

    *(pont2 + j) = EEPROM.read(i);

    j++;

  }

  return num2;

}

Na leitura a ideia é a mesma. Aqui a variável num2 é composta byte a byte para formar o float resultante.

Essa estratégia funciona pra qualquer tipo, int, long, Double, etc. Basta adaptar os tipos dos ponteiros.

----

Exibições: 2499

Responder esta

Respostas a este tópico

Olha só um float é representado por 4 bytes se a intensão é transmitir este float usando a menor quantidade de bytes possível então a melhor forma seria transformar o float em uma sequencia de bytes e depois transmitir e em seguida fazer a conversão, veja como:

https://gist.github.com/rodrigopmatias/6417147

Também pode ser feito assim:

union acesso_float     { float f ;   int b[4];    };       //declaração de struct


union acesso_float    x_f ;                                 

uso:      x_f .float = variavel_float;

            but_tx[n+0] = x_f.b[0];

            ...

            but_tx[n+3] = x_f.b[3];

Não tinha que ser byte b[4] ou char b[4]?

Digo isso porque um int tem mais de um byte.

me desculpe errei, é char b[4]. 

Sim foi o que fiz no código que postei no github

para falar a verdade só precisava de duas linhas para fazer isto:

char * floatb;

float number;

number = 100.25;

floatb = (char *)(&number);

Só isto já basta

Show isso mesmo,tambem achei bem interessante o método do Valter.

vlw pela força.

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço