2010-07-17 26 views
7

¿Cuál es la mejor manera de enviar float, double y int16 en serie en Arduino?Cómo enviar float a través de la serie

El Serial.print() solo envía valores como ASCII codificados. Pero quiero enviar los valores como bytes. Serial.write() acepta byte y bytearrays, pero ¿cuál es la mejor manera de convertir los valores en bytes?

Traté de lanzar un int16 a un byte*, sin suerte. También utilicé memcpy, pero eso se usa para muchos ciclos de CPU. Arduino usa C/C++ simple. Es un microcontrolador ATmega328.

+0

posible duplicado de [cómo dar salida a un int en binario?] (Http://stackoverflow.com/questions/3269767/how-to-output-an-int-in-binary) –

Respuesta

9

Sí, enviar estos números hay que convertirlos primero en ASCII cuerdas. Si está trabajando con C, sprintf() es, IMO, la forma más práctica de hacer esta conversión:

[Agregado después: AAAGHH! Olvidé que para ints/longs, el argumento de entrada de la función quiere ser unsigned. Del mismo modo para el formato de cadena entregado a sprintf(). Así que lo cambié a continuación. Lo siento por mi terrible supervisión, que habría sido un error difícil de encontrar. Además, ulong hace un poco más general.]

char * 
int2str(unsigned long num) { 
    static char retnum[21];  // Enough for 20 digits plus NUL from a 64-bit uint. 
    sprintf(retnum, "%ul", num); 
    return retnum; 
} 

Y similar para los flotadores y dobles. El código que realiza la conversión se conoce de antemano. Hay que decir qué tipo de entidad está convirtiendo, por lo que puede terminar con las funciones char *float2str(float float_num) y char *dbl2str(double dblnum).

Obtendrá una cadena de caracteres terminada en NUL (sin espacios en blanco o ceros) ajustada a la izquierda fuera de la conversión.

Puede hacer la conversión en cualquier lugar/de cualquier forma que desee; estas funciones son solo ilustraciones.

10

hm. ¿Qué tal esto:

void send_float (float arg) 
{ 
    // get access to the float as a byte-array: 
    byte * data = (byte *) &arg; 

    // write the data to the serial 
    Serial.write (data, sizeof (arg)); 
} 
+0

me gano. – hjhill

+2

Si se envían como bytes, binarios por definición, es posible que no funcionen: algunos de los bytes se verán como caracteres de control en los que el receptor probablemente actuará. Entonces los números tienen que ser ascii -ized. Además, los caracteres se envían casi siempre como siete bits a través de una línea serie, por lo que tratar de enviarlos como bytes de 8 bits eliminará el bit de orden superior. –

+1

Esta forma de transmitir datos no funcionará si el emisor y el receptor tienen una endianidad diferente. –

3

Utilice el protocolo Firmata. Cita:

Firmata es un protocolo genérico para comunicarse con los microcontroladores del software en una computadora host. Está diseñado para funcionar con cualquier paquete de software de computadora host . En este momento hay un objeto coincidente en un número de de idiomas. Es fácil agregar objetos para otro software al use este protocolo. Básicamente, este firmware establece un protocolo para hablando con el Arduino desde el software del host. El objetivo es permitir a las personas controlar completamente el Arduino del software en la computadora host .

2

La palabra de jerga que debe buscar es "serialización".

Es un problema interesante con respecto a una conexión serie que puede tener restricciones sobre qué caracteres pueden ir de extremo a extremo, y puede que no sea capaz de pasar ocho bits por carácter tampoco.

Las restricciones en ciertos códigos de caracteres son bastante comunes. Aquí están algunos fruto de la casualidad:

  • Si el control de flujo de software está en uso, entonces convencionalmente los caracteres de control DC1 y DC3 (Ctrl-Q y Ctrl-S, también llamado a veces XON y XOFF) no pueden ser transmitidos como datos porque se envían para iniciar y detener el remitente en el otro extremo del cable.

  • En algunos dispositivos, los caracteres NUL y/o DEL (0x00 y 0x7F) simplemente pueden desaparecer del FIFO del receptor.

  • Si el receptor es Unix tty, y los modos de termio no están configurados correctamente, el carácter Ctrl-D (EOT o 0x04) puede hacer que el controlador tty señale un final de archivo al proceso que tiene el tty abierto.

Una conexión en serie generalmente se puede configurar para el ancho de bytes y la posible inclusión de un bit de paridad. Algunas conexiones requerirán que se utilice un byte de 7 bits con paridad, en lugar de un byte de 8 bits. Incluso es posible la conexión al hardware heredado (muy viejo) para configurar muchos puertos serie para bytes de 5 y 6 bits. Si hay menos de 8 bits disponibles por byte, se requiere un protocolo más complicado para manejar los datos binarios.

ASCII85 es una técnica popular para evitar los datos de 7 bits y las restricciones en los caracteres de control. Es una convención para volver a escribir datos binarios utilizando solo 85 códigos de caracteres ASCII cuidadosamente seleccionados.

Además, ciertamente tiene que preocuparse por el orden de bytes entre el emisor y el receptor. También podría tener que preocuparse por el formato de punto flotante, ya que no todos los sistemas usan el punto flotante IEEE-754.

En pocas palabras, la mejor respuesta es elegir un protocolo ASCII puro. Tiene la ventaja de que puede ser entendido por un humano, y es mucho más resistente a los problemas con la conexión en serie. A menos que esté enviando montones de datos de punto flotante, la ineficacia de la representación puede ser compensada por la facilidad de implementación.

Sé liberal en lo que aceptas y conservador en lo que emites.

0

Quizás esa sea la mejor forma de convertir Float a Byte y Byte a Float, -Hamid Reza.

int breakDown(int index, unsigned char outbox[], float member) 
{ 
    unsigned long d = *(unsigned long *)&member; 

    outbox[index] = d & 0x00FF; 
    index++; 

    outbox[index] = (d & 0xFF00) >> 8; 
    index++; 

    outbox[index] = (d & 0xFF0000) >> 16; 
    index++; 

    outbox[index] = (d & 0xFF000000) >> 24; 
    index++; 
    return index; 
} 


float buildUp(int index, unsigned char outbox[]) 
{ 
    unsigned long d; 

    d = (outbox[index+3] << 24) | (outbox[index+2] << 16) 
    | (outbox[index+1] << 8) | (outbox[index]); 
    float member = *(float *)&d; 
    return member; 
} 

respetos. `

0

Las estructuras y los sindicatos resuelven ese problema. Use una estructura empaquetada con una unión de tamaño byte que coincida con la estructura. Superponga los punteros a la estructura y unión (o agregue la unión en la estructura). Usa Serial.write para enviar la transmisión. Tener una estructura/unión correspondiente en el extremo receptor. Siempre que el orden de bytes coincida con el problema, de lo contrario puede descomprimir utilizando las funciones "C" hto (s..l). Agregue información de "encabezado" para decodificar diferentes estructuras/uniones.

Cuestiones relacionadas