Arduino Forum

International => Español => Topic started by: 111---111 on Feb 01, 2011, 08:38 am

Title: Como separar int o long en bytes
Post by: 111---111 on Feb 01, 2011, 08:38 am
Igual es algo obvio para muchos, pero al mismo tiempo para gente como yo que ha empezado a programar hace mas bien poco no lo es tanto y cosas que pueden ser de cajón o simplemente automáticas para muchos, se convierte en toda una odisea para otros.

Os pido si puede ser, ejemplos de como desglosar, trocear o separar enteros o longs en bytes para luego por separado meterlos en un array, enviarlos por serial, meterlos en memoria o simplemente, tratar los datos por separado.


Saludos
Title: Re: Como separar int o long en bytes
Post by: anv on Feb 01, 2011, 09:04 am

Igual es algo obvio para muchos, pero al mismo tiempo para gente como yo que ha empezado a programar hace mas bien poco no lo es tanto y cosas que pueden ser de cajón o simplemente automáticas para muchos, se convierte en toda una odisea para otros.

Os pido si puede ser, ejemplos de como desglosar, trocear o separar enteros o longs en bytes para luego por separado meterlos en un array, enviarlos por serial, meterlos en memoria o simplemente, tratar los datos por separado.
Saludos


Yo lo haría más o menos así:

long l;
byte b[4];
.... a toma algun valor

b[0]=l & 0xff;  // hago and con 0xff para que quede solo el ultimo byte
b[1]=(l>>8) & 0xff; // roto los bits 8 veces a la derecha y de nuevo me quedo con el ultimo byte
b[2]=(l>>16) & 0xff;
b[3]=(l>>24) & 0xff;

Si el valor de l se puede perder, se puede if haciendo >>8 sobre l varias veces en lugar de hacerlo dentro de la asignacion. También se podría copiar l a una variable auxiliar. Todo depende de si en tu programa ahorrar algunos microsegundos es importante o no.
Title: Re: Como separar int o long en bytes
Post by: 111---111 on Feb 01, 2011, 10:34 am
Gracias anv, he estado probando lo siguiente y modificando varias cosas pero no me funciona :smiley-red:, me salen caracteres raros.


Code: [Select]

byte dato[3];
int datos=1234;

void setup(){
 Serial.begin(115200);

 dato[0]=datos & 0xff;
 dato[1]=(datos>>8) & 0xff;
 dato[2]=(datos>>16) & 0xff;
 dato[3]=(datos>>24) & 0xff;
 
 Serial.println(dato[0]);
 Serial.println(dato[1]);
 Serial.println(dato[2]);
 Serial.println(dato[3]);
}

void loop(){
}


Title: Re: Como separar int o long en bytes
Post by: xlopez on Feb 01, 2011, 11:25 am
Donde has puesto byte dato[3] debes poner byte dato[4] porque un entero ocupa 4 bytes, no 3.

Es normal que te salgan chinos, los caracteres imprimibles son los valores asciii superiores al 32, y aún así algunos son muy extraños.
Title: Re: Como separar int o long en bytes
Post by: 111---111 on Feb 01, 2011, 12:00 pm
Lo del 3 en el array se me ha debido colar, como he estado inicializando el array de varias maneras...pero gracias por la aclaración que siempre viene bien!  XD
Acabo de hacer lo siguiente para ver si consigo verlos al imprimirlos pero nada, creo que no me queda claro el concepto...

También lo he leído con el RealTerm y me saca 02,34,30,30 en HEX y debería sacar 31,32,33,34 no?

Code: [Select]

byte dato[4];
int datos=1234;

void setup(){
 Serial.begin(115200);

 dato[0]=(datos & 0xFF) + 48;
 dato[1]=((datos >> 8) & 0xFF) + 48;
 dato[2]=((datos >> 16) & 0xFF) + 48;
 dato[3]=((datos >> 24) & 0xFF) + 48;
 
 Serial.println(dato[0]);
 Serial.println(dato[1]);
 Serial.println(dato[2]);
 Serial.println(dato[3]);
}

void loop(){
}
Title: Re: Como separar int o long en bytes
Post by: chato_sat on Feb 01, 2011, 02:15 pm
1º un número en arduino son 2 bytes.
2º estás dividiendo el número en bytes, no en caracteres ascii. El número 1234 está formado por los bytes 0x04 y 0xd2. Si lo que quieres hacer es dividirlo en los número 1, 2, 3 y 4 prueba esto:
Code: [Select]

byte dato[4];
int datos=1234;

void setup() {
 dato[0]=datos%10;
 dato[1]=(datos/10)%10;
 dato[2]=(datos/100)%10;
 dato[3]=(datos/1000)%10;
}


Aunque no tenga nada que ver con el post te tengo que preguntar si eres de Murcia?? es que por el nick parece que eres vecino mio, jeje

Saludos chato_sat
Title: Re: Como separar int o long en bytes
Post by: 111---111 on Feb 01, 2011, 02:56 pm
Muchas gracias por la explicación y el ejemplo, he hecho lo siguiente y he podido ver la cifra en ascii por serie perfectamente:

Code: [Select]

  dato[0]=((datos/1000)%10)+48;
  dato[1]=((datos/100)%10)+48;
  dato[2]=((datos/10)%10)+48;
  dato[3]=(datos%10)+48;


Concretamente, que hace el %10? lo he leído en el Reference, pero me he quedado igual... :smiley-red:

Por cierto, no soy de murcia, soy del centro, pero si sé que hay una ciudad que se llama Ricote por tu tierra  ;)
Title: Re: Como separar int o long en bytes
Post by: chato_sat on Feb 01, 2011, 04:14 pm

Concretamente, que hace el %10? lo he leído en el Reference, pero me he quedado igual... :smiley-red:


De nada, para una cosa en la que sí puedo ayudar lo tenía que hacer ;)

El % lo único que hace es calcular el resto de la división. Es común para todos los lenguajes de programación (por lo menos que yo conozca).
Title: Re: Como separar int o long en bytes
Post by: 111---111 on Feb 01, 2011, 04:23 pm
Madre mía, he tenido que hacer una división en papel para comprenderlo XD XD XD XD ya me vale...

Gracias de nuevo ;)
Title: Re: Como separar int o long en bytes
Post by: xlopez on Feb 01, 2011, 07:43 pm
Pero recuerda que un entero puede valer desde -32768 a +32767.

No te sirve un byte[4], necesitas un byte[5] para los números y antes hacer la comprobación del signo.

Code: [Select]

byte dato[5];
int datos=-12345;

void setup() {
   Serial.begin(9600);
}
void loop(){
 int absdatos;
 if (datos<0){
   absdatos=-datos;
 } else{
   absdatos = datos;
 }
 dato[0]=absdatos%10+48;
 dato[1]=(absdatos/10)%10  +48;
 dato[2]=(absdatos/100)%10 +48;
 dato[3]=(absdatos/1000)%10 +48;
 dato[4]=(absdatos/10000)%10 +48;

 if (datos < 0){
     Serial.print('-');
 }
 Serial.print(dato[4]);
 Serial.print(dato[3]);
 Serial.print(dato[2]);
 Serial.print(dato[1]);
 Serial.println(dato[0]);
 delay(500);
}

Y un long necesita un byte[10];
Title: Re: Como separar int o long en bytes
Post by: 111---111 on Feb 01, 2011, 08:12 pm
Ok muchas gracias!!! No había tenido en cuenta la comprobación de signo pero si me puede hacer falta, y saber los limites del int y del long también.
La verdad que me está siendo muy instructivo este hilo  ;)
Title: Re: Como separar int o long en bytes
Post by: Juantreras on Feb 11, 2011, 08:08 pm
Hola a todos,hace unas semanas abrí un hilo titulado "Enviar un dato float via serial" el cual me contesto Xlopez ofreciéndome una solución (gracias Xlopez) pero que yo no he sido capaz de adaptarla.Ahora veo esto que parece se acerca mas a lo que necesito.Os explico: tengo un Arduino "B" que lee los datos de un anemómetro,lee las revoluciones y calcula cada 10 segundos el dato "float speedwind", desde un Arduino "A" le envío a través de un xbee una orden y el Arduino "B" obedece y "Serial.print (windspeed); me envía la lectura y yo en el Arduino "A" lo visualizo en un lcd , hasta aquí sin problemas, pero, aquí viene mi problema, necesito que aparte de visualizarlo en el lcd actualice el valor "windspeed" en el Arduino A.Tengo que descomponer el dato en "B" y enviarlo a "A" y aquí volverlo a armar para actualizarlo y almacenarlo . He probado mil cosas y no he dado con la solución.¿Alguna idea?, actualmente estoy bloqueado con esto.
Muchas gracias y un saludo
Title: Re: Como separar int o long en bytes
Post by: igorreal on Feb 11, 2011, 09:00 pm
Hay diferentes formas de "atacar" el problema....

1) Mandas el dato en "raw", es decir, tal cual lo lees sin hacer ninguna operacion. A ver si me explico mejor.... XD
Si estas midiento pulsos, imagino que estaras usando una variable de tipo byte o unsigned int (2 bytes) como contador, no?
Puedes enviar este byte o estos dos, y en el otro lado haces la operacion de dividir entre el tiempo y el numero de pulsos por vuelta, etc.
2) Mandas el float tal cual (4 bytes).

Para mandar el dato en ambas opciones, descompones en bytes (depende del tipo de variable que quieras descomponer) con las operaciones bitwise que han explicado mas arriba y usa Serial.print(mibyte,BYTE).
En el otro lado, tienes que "componerlo" consecuentemente a como lo has "descompuesto".
Imaginemos un unsigned int (ocupa dos bytes):

unsigned int micontadorpulsos;   //la variable que aumento cada vez que recibo un pulso nuevo
byte byte_bajo;
byte byte_alto;
byte_bajo=micontadorpulsos & 255;
byte_alto=(micontadorpulsos >> 8 ) & 255;

Serial.print(byte_bajo,BYTE);
Serial.print(byte_alto,BYTE);

En el otro Arduino, ya sabes que primero te va a llegar la parte baja, y luego la alta.
Por lo cual tienes que hacer (asumo que has leido los dos bytes con Serial.read() ):

unsigned int mivariablerecepcion;
mivariablerecepcion=(byte alto << 8 ) ¦ (byte_bajo);


Espero que sirva



Saludos




Igor R.
Title: Re: Como separar int o long en bytes
Post by: igorreal on Feb 11, 2011, 09:11 pm
Lo suyo es que implementases un pequenyo miniprotocolo, para saber cuando empieza un nuevo dato, y cuando acaba.
Es decir, algo como SminumeroF
* "S" de start (lo mandas en Ascii)
* minumero el dato a enviar, lo mandas con la opcion byte (tantos bytes como kieras). Es decir Byte0Byte1Byte2.....
* "F" de fin (lo mandas en Ascii).

Asi es facil hacerte una "maquina de estados" => http://real2electronics.blogspot.com/2009/10/linksys-arduino.html
Puedes coger de ahi la "idea". Solo el tema del diagrama de estados y el mini programa de Arduino de ejemplo.

Espero no haberte liado mas.... ]:D

Nota.- Cuando escribo un post largo, el textbox  de crear el mensaje se me sube siempre hacia arriba, por lo que tengo que andar bajando con el scroll.... alguien sabe como evitar esto???
Title: Re: Como separar int o long en bytes
Post by: Juantreras on Feb 12, 2011, 07:00 pm
Hola a todos: parece que veo luz al final del tunel,o no....He sido capaz de descomponer el dato enviarlo y volverlo a montar al otro lado pero en... I2c , no en Serial.
Vamos a ver el la parte del emisor:
Quote

unsigned int micontadorpulsos=1550;   //la variable que aumento cada vez que recibo un pulso nuevo
byte byte_bajo;
byte byte_alto;
void setup() {

  Serial.begin(9600);
}

void loop(){
 byte_bajo=micontadorpulsos & 255;
byte_alto=(micontadorpulsos >> 8 ) & 255;
 
  
Serial.print(byte_bajo,BYTE);
Serial.print(byte_alto,BYTE);
delay (2000);
}


Pero tengo problemas a la hora de recepcionarlo.Esta linea me da error al compilar"mivariablerecepcion =((byte_alto << 8 )| (byte_bajo));"no acabo de dar con la solución.




Juan

Title: Re: Como separar int o long en bytes
Post by: chato_sat on Feb 14, 2011, 10:05 am
Hola Juantreras, intenta probar con el siguiente código en el emisor:
Code: [Select]

unsigned int micontadorpulsos=1550;   //la variable que aumento cada vez que recibo un pulso nuevo
byte byte_bajo;
byte byte_alto;
void setup() {

  Serial.begin(9600);
}

void loop(){
  byte_bajo=micontadorpulsos & 255;
  byte_alto=(micontadorpulsos >> 8 ) & 255;

  Serial.print('S', BYTE);
  Serial.print(byte_bajo,BYTE);
  Serial.print(byte_alto,BYTE);
  Serial.print('F', BYTE);
  delay (2000);
}


Y el siguiente en el lado del receptor:
Code: [Select]

byte byte_bajo;
byte byte_alto;
unsigned int contadorPulsos;

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

void loop() {
  //Compruebo si han llegado datos por el puerto serie
  if (Serial.available() > 0) {
    //Si el dato que ha llegado es S significa que comienza la transmisión
    //del contador de pulsos.
    if (Serial.read() == 'S') {
      byte_bajo = Serial.read(); //Leo el byte_bajo del puerto serie
      byte_alto = Serial.read(); //Leo el byte_alto del puerto serie
      contadorPulsos = ((byte_alto << 8) && (byte_bajo)); //Junto todo en una variable
      Serial.read(); //Como el protocolo envia una F la leo y en este caso la
                      //desecho porque no la necesito para nada
    }
  }
}


En este caso las tramas se envían con un protocolo como ha dicho Igor_R que es Sbyte_bajobyte_altoF.

Espero que te pueda ayudar.

Saludos chato_sat

Title: Re: Como separar int o long en bytes
Post by: igorreal on Feb 14, 2011, 10:13 am
Lo unico que:
contadorPulsos = ((byte_alto << 8 ) && (byte_bajo));  
deberia ser una OR, no una AND. Y de operaciones bitwise => http://arduino.cc/en/Reference/BitwiseAnd  (quieres sumar la parte alta a la baja).
&& devuelve true or false (es una operacion logica que devuelve boolean). Es diferente "&" que "&&".
Y es bueno comprobar que llegaba una F a lo ultimo ( para eso te "curras" el protocolo... ;) ) y asi validar que puedes "confiar" que has recibido bien los datos.



:D

Title: Re: Como separar int o long en bytes
Post by: jose_francisco on Feb 15, 2011, 08:52 pm
Para el caso de leer o escribir en EEPROM busca las funciones:
http://www.arduino.cc/playground/Code/EEPROMWriteAnything

No se por que no están "de serie" en arduino.
Title: Re: Como separar int o long en bytes
Post by: Juantreras on Feb 20, 2011, 01:39 pm
Bueno chicos ,primero un saludo para todos,disculpar la tardanza en contestar, he estado muy liado.Bueno al lío ,efectivamente, Igor, el código funciono perfectamente pero no con && si no con | como decías , además el implementar ese sencillo protocolo da un control "total" sobre el flujo de datos, me ha venido de perlas para otra parte del proyecto que se dedica a recopilar datos y que no acababa de ir como debiera, así es que ha sido un "math" en toda regla.
Bien ahora , ya solo por culturilla general ¿que diferencia hay entre esta expresión? :RPM = ( Wire.receive()<<8) +Wire.receive(); y esta otra: RPM = ((byte_alto << 8) | (byte_bajo)); por supuesto a parte de que una es usada en comunicación I2c y la otra en Serial.
Gracias a todos
 

Title: Re: Como separar int o long en bytes
Post by: chiva on Feb 20, 2011, 01:50 pm
mmm, ninguna 8)
Title: Re: Como separar int o long en bytes
Post by: ASTROCAR on Aug 13, 2011, 02:21 pm
Hola buenos me remiti a este post por otr de can bus y que iso referencia el colega igor bueno en fin paso a decirle que he notado todo un algoritmo matemadico para separar byte pero nose si fue que lo olvidaron o no lo han visto o usado nunca pero existen los comando lowByte() y highByte().

en la referencia hay informacion necesaria para esto ahora lo explico a mi manera ejemplo se tiene una variable word como ya he visto en sus ejemplo;
word dato=0x45f2;

para separar esa variable de 16 bit basta con usar los comando que les mensiones es decir:
Para el byte alto se usa highByte(dato) y para el bajo lowByte(dato)
de manera ejemplo:
byte alto=0;
byte bajo=0;
entonce;

alto=highByte(dato);
bajo=lowByte(dato);
donde alto=0x45 y bajo=0xf2

caso contario si se quiere unir dos byte se usa los mismo comando pero de esta manera;
highByte(dato)=0x45; y lowByte(dato)=0xf2;
ya  con eso la variable dato ahora toma el valor 0x45f2.

Saludos y espero haberme hecho entender.
Title: Re: Como separar int o long en bytes
Post by: Valen on Aug 16, 2011, 11:47 am
Hola, una forma sencilla es apuntar el dato (da igual que sea int, long, etc.) por un puntero a byte (o a char, que en el fondo, es lo mismo):

// Dato almacenado en un int.
int iDato = 5494;   //  (por ejemplo.....)

// Puntero a char (o a byte), para manejar el dato recibido, byte a byte.
char *pDato = (char *) &iDato;

// Ahora, cada uno de los bytes lo puedes leer así:
// Sin olvidarse que el int mide solo dos bytes.

byte Byte_01 =  pDato[0];

byte Byte_02 =  pDato[1];


// Esto es asi porque el puntero a char apunta a datos de un byte de longitud.