Recibiendo bytes por puerto serie

Buenas. Estoy intentando recibir una serie de bytes por puerte serie. Concretamente estoy intentando recibir 4 bytes que transmito desde Matlab/Simulink, que se corresponden a dos números int16. De esta manera, los dos primeros bytes se corresponden con un número y los dos siguientes con otro número.
El caso es que he realizado un código para recibir estos datos, pero no se me ocurría como comprobar que Arduino los recibía correctamente. Se me ha ocurrido encender un LED si uno de los números cambia del valor inicial, pero el LED no se enciende. También se me ocurrió escribir por puerto serie el valor de una de las variables, pero vale 0 constantemente. Quizás el código es incorrecto, lo dejo por aquí a ver si vosotros detectáis algún fallo:

byte buffIn[4]={0, 0, 0, 0};
long int ref1=0;
long int ref2=0;
const int ledPIN=9;

void setup() {
  Serial.begin(9600);
  pinMode(ledPIN, OUTPUT);
}

void loop() {
 if (Serial.available() >= 4)
 {
  Serial.readBytes(buffIn,4);
  ref1=(long int)buffIn[1] << 8 | (long int)buffIn[0];
  ref2=(long int)buffIn[3] << 8 | (long int)buffIn[2];
 }
 if (ref1!=0)
  digitalWrite(ledPIN,HIGH);
  
 Serial.println(ref1);
}

La condicion if (Serial.available() >= 4) es incorrecta ,solo se va a cumplir cuando en el buffer haya 4 o mas bytes ,pero si envias 4 bytes ,en el momento en que lees el primero ,este se borra del buffer y solo quedan 3,la condicion no se cumple.En definitiva usa if (Serial.available() > 0) o en un solo bucle while(Serial.available() > 0)

Lo primero decirte que no deberias usar los pines 0 y 1 y configurar otro par de pines digitales con la libreria SoftwareSerie.

También debes tener en cuenta la recomendacion de jose.

El tema es que hagas de descomposición correcta del int en dos bytes y envíes correctamente. Luego en Arduino haces la inversa. Por experiencia te cuento que lo mas fácil es mostrarlos cada byte en HEXadecimal (00~FF).

Te pongo un ejemplo de como descomponer y recomponer un entero en dos bytes.

void setup(){
   Serial.begin(9600);
   //Descomponer
   int dat1 = 12345;
   Serial.println(dat1, HEX);     //0x3039
   byte val1 = highByte(dat1);   //0x30 (MSB)
   byte val2 = lowByte(dat1);    //0x39 (LSB)
   Serial.println("-------");
   //Reconstruir
   int dat2;
   dat2 = val1;                  //Tomamos MSB
   dat2 <<= 8;                   //Desplazamos 8 bits a la izquierda
   dat2 |= val2;                 //Añadimos LSB
   Serial.println(dat2, HEX);     //0x3039
   Serial.println(dat2);            //12345
}

void loop(){
   //Nada
}

Antes que nada, muchas gracias a ambos por vuestras aportaciones.

jose:
La condicion

if (Serial.available() >= 4)

es incorrecta ,solo se va a cumplir cuando en el buffer haya 4 o mas bytes ,pero si envias 4 bytes ,en el momento en que lees el primero ,este se borra del buffer y solo quedan 3,la condicion no se cumple.En definitiva usa

if (Serial.available() > 0)

o en un solo bucle

while(Serial.available() > 0)

Entonces debería cambiar cómo recibo los bytes, no sólo el inicio del bucle, ¿no? A mí se me ha ocurrido esto:

for (i=0; i++; i<=4)
 {
  if(Serial.available()>0)
    Serial.readBytes(buffIn,i);
 }
ref1=(long int)buffIn[1] << 8 | (long int)buffIn[0];
ref2=(long int)buffIn[3] << 8 | (long int)buffIn[2];

Es que si sólo cambio la condición del bucle y dejo esto:

while (Serial.available() >=0)
 {
  Serial.readBytes(buffIn,4);
  ref1=(long int)buffIn[1] << 8 | (long int)buffIn[0];
  ref2=(long int)buffIn[3] << 8 | (long int)buffIn[2];
 }

Entiendo que siempre se me sobreescribiría la misma posición de la variable "buffIn". De todas formas he probado con ambos códigos y sigo recibiendo 0 :confused:

Kike_GL:
Lo primero decirte que no deberias usar los pines 0 y 1 y configurar otro par de pines digitales con la libreria SoftwareSerie.

También debes tener en cuenta la recomendacion de jose.

El tema es que hagas de descomposición correcta del int en dos bytes y envíes correctamente. Luego en Arduino haces la inversa. Por experiencia te cuento que lo mas fácil es mostrarlos cada byte en HEXadecimal (00~FF).

Te pongo un ejemplo de como descomponer y recomponer un entero en dos bytes.

void setup(){

Serial.begin(9600);
  //Descomponer
  int dat1 = 12345;
  Serial.println(dat1, HEX);    //0x3039
  byte val1 = highByte(dat1);  //0x30 (MSB)
  byte val2 = lowByte(dat1);    //0x39 (LSB)
  Serial.println("-------");
  //Reconstruir
  int dat2;
  dat2 = val1;                  //Tomamos MSB
  dat2 <<= 8;                  //Desplazamos 8 bits a la izquierda
  dat2 |= val2;                //Añadimos LSB
  Serial.println(dat2, HEX);    //0x3039
  Serial.println(dat2);            //12345
}

void loop(){
  //Nada
}

Entiendo que usar los pines 0 y 1 puede dar lugar a problemas, pero cuando configure otro par de pines digitales utilizando SoftwareSerial, no sé como indicar a Matlab/Simulink que utilice esos pines y no los predeterminados. Tampoco sé si en realidad hace falta hacerlo o el propio software interpreta por sí mismo cómo enviar la información.
Con respecto a la descomposición, he probado el código que has puesto y creo que la descomposición que yo hago es la misma que haces en el código, ¿verdad? Desplazas 8 bits a la izquierda los bits más significativos y añades los bits menos significativos:

ref1=(long int)buffIn[1] << 8 | (long int)buffIn[0];
 ref2=(long int)buffIn[3] << 8 | (long int)buffIn[2];

Desconozco el funcionamiento de matlab,pero si puedes enviar el numero int directamente en vez de en dos bytes ,tal vez podrias recogerlo con Serial.parseInt()

No deberias leer 4 bytes sino solo 2 bytes. Ademas te estas olvidando que por el puerto serie pasan byte que son recibidos en formato ASCII.

byte ref[2];
while (Serial.available()) {
  Serial.readBytes(ref, 2);
  Serial.println(ref[0]);   //Primer byte
  Serial.println(ref[1]);   //Segundo byte
}

Si envío "23" entonces veras que se imprime el ASCII 50 (2) y ASCII 51 (3).

Quizas te sirva mas:

int valor = Serial.parseInt();

Ojo que solo puede leer digitos. Si envias 123ABC o ABC123 te retornara 123, si envias ABC te retornara 0.