Go Down

Topic: Función para partir y unir un float (Read 1 time) previous topic - next topic

Jose Francisco

Buenas.

Por necesidades varias necesito coger un float y guardarlo como dos int (para transmitirlo por modbus); luego tengo que coger esos dos ints y volver a componer el float.

Dicho de otra manera.
-Crear un float
-Meter los dos primero bytes en un int
-Meter los dos segundos bytes en otro int
-transmitirlos por modbus (eso ya lo tengo en marcha)
-volver a componer el float en base a los dos ints

He echado un vistazo a las operaciones

Code: [Select]
#include <WProgram.h>
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
    const byte* p = (const byte*)(const void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
  EEPROM.write(ee++, *p++);
    return i;
}

template <class T> int EEPROM_readAnything(int ee, T& value)
{
    byte* p = (byte*)(void*)&value;
    int i;
    for (i = 0; i < sizeof(value); i++)
  *p++ = EEPROM.read(ee++);
    return i;
}


y se que aqui tengo la respuesta, pero no lo saco.

¿Alguna manita?

Gracias.

chiva

#1
Jun 17, 2012, 02:30 am Last Edit: Jun 17, 2012, 02:34 am by chiva Reason: 1
Si no funciona lo que te comento puedes utilizar la forma que se ha comentado alguna vez en el foro: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1207242838
Debería estar en español por aquí, pero no lo encuentro mirando por encima.

Prueba con esto, a ver que tal funciona.

Code: [Select]

int send(const float& value)
{
   const int* p = (const int*)(const void*)&value;
   for (int i = 0; i < sizeof(value)/sizeof(int); i++)
 MODBUS.SEND(*p++);
   return i;
}

int read(float& value)
{
   int* p = (int*)(void*)&value;
   for (int i = 0; i < sizeof(value)/sizeof(int); i++)
 *p++ = MODBUS.READ();
   return i;
}
Mercadillo electrónico. Kit iniciación a Arduino, shield LCD a color y más cosas!

curro92

Hola,
También podrías declarar una  union, que es una estructura de C que puede contener varias cosas distintas. Una vez comenté esa posibidad en el foro: http://arduino.cc/forum/index.php/topic,69929.0.html


chiva


Hola,
También podrías declarar una  union, que es una estructura de C que puede contener varias cosas distintas. Una vez comenté esa posibidad en el foro: http://arduino.cc/forum/index.php/topic,69929.0.html

Mira el primer enlace que he puesto XD
Mercadillo electrónico. Kit iniciación a Arduino, shield LCD a color y más cosas!

Jose Francisco

Ostras, union hace la fuerza
Voy a probarlo

Jose Francisco

Ya estoy de vuelta.

Con un servidor modbus en mi pc le puedo mandar el float partido en dos ints.
Esto lo hace bien y luego puedo recuperarlo de igual manera con el PC.

El problema viene cuando quiero volver a montar esos dos ints en un float y escribirlo en puerto serie.

El codigo que tengo es más o menos:


Code: [Select]


//fuera de setup y loop

unsigned int regs1[21];

union {
unsigned int ints[2];
float toFloat;
} foo;

void loop {

  foo.ints[0]=regs1[15];
  foo.ints[1]=regs1[16];

}


void contestar{

      Serial.println(foo.ints[0]);
      Serial.println(foo.ints[1]);
      Serial.println(foo.toFloat);
}



Eso está resumido.
Cuando llamo a "contestar" me aparece:
4059
16457
0.00

El float que debería aparecer es 3.141592654 (aprox)

Creo que el problema está en la implementación del float. Es decir: el pc ha mandado 2 ints que luego él sabe componer, pero arduino no.
¿Puede ser?
¿opiniones, ideas?

curro92

#6
Jun 18, 2012, 05:42 am Last Edit: Jun 18, 2012, 05:54 am by curro92 Reason: 1
Hola,

Prueba con este ejemplo, el Serial.print a mí me da 3.141593
Code: [Select]


union
{
  unsigned int ints[2];
  float toFloat;
} foo;


void setup()
{
   Serial.begin(9600);
}   
   

   
void loop()
{
  // 3.141593
  foo.ints[0]=4059;
  foo.ints[1]=16457;

  Serial.println(foo.toFloat, 6); // con 6 decimales
  Serial.println(foo.ints[0]);
  Serial.println(foo.ints[1]);
  Serial.println("");
  delay(500);
}





Jose Francisco

Pues a mi me da...

Code: [Select]

0.000000
4059
16457

0.000000
4059
16457



Y ahora es cuando yo digo... es que no estoy usando Arduino, estoy usando una chipkit max32.
Pero... ¿No debería dar igual?

Un saludo.

matiasdelellis

Sin mirar muhco tu codigo..
Y si enviás como dos intetegers directamente?? La parte entera como tal, y la real la "convertis" a un entero.. Algo parecido se usa para imprimir floats en LCDs..

mm. Ejemplo..

float = 2.25

entero = int(2.25); // entero = 2
enviar(entero);

real = (float - entero) * 100;  // real = 25
enviar(real);

Despues tenes que hacer algo parecido para recuperar el dato.

Jose Francisco

Buenos dias.

1) No puedo usar el método de partir entero y decimal por que no puedo elegír la manera. Ya me viene el float en 4 bytes

2) Creo que ya se el motivo de que no funcione el union. Chipkit utiliza enteros de 4 bytes, con lo cual no sirve para la carambola. Intentaré hacer algo como:

Code: [Select]

union
{
  unsigned short shorts[2];   //o uint16_t
  float toFloat;
} foo;


void setup()
{
   Serial.begin(9600);
}   
   

   
void loop()
{
  // 3.141593
  foo.ints[0]=4059;
  foo.ints[1]=16457;

  Serial.println(foo.toFloat, 6); // con 6 decimales
  Serial.println(foo.ints[0]);
  Serial.println(foo.ints[1]);
  Serial.println("");
  delay(500);
}


Cuando pueda lo probaré.

Un saludo, y muchas gracias.

Jose Francisco

Efectivamente.

int en Chipkit usa 4 bytes. Cuando he usado dos short para montar un float ha salido bien.

Muchas gracias compañeros.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy