Error en comparación de valores numéricos desde el buffer

Hola, tengo un código muy simple, pero se comporta de una manera que no tiene lógica, y ya no se si es problema mio o del Arduino, me explico.

Tengo un programita en C# que carga un buffer y lo envía al Arduino mediante el USB COM, el Arduino lo procesa y dependiendo de ciertos valores del buffer muestra en un display TM1368 unos mensajes u otros, hasta aquí todo bien, pero al parecer funciona bien en unos casos y no en otros.

Este es mi buffer:

El cual envío de esta manera al COM (Código C#)

SerialPort PuertoSerie;

byte[] buffer;

byte[] buffer = new byte[34];

PuertoSerie = new SerialPort("COM3", 9600, Parity.None, 8);

PuertoSerie.Open();

PuertoSerie.Write(buffer, 0, 34);

PuertoSerie.Close();

Y en el Sckecth tengo esto:

#include <TM1638.h>
#include <stdlib.h>

const int DATA_PIN = 5;
const int CLOCK_PIN = 6;
const int STROBE_PIN = 7;

String FlatMessage, TyreMesage;
byte values[34];
const int TRAMA_LENGTH = 34;
const int WEAR_LIMIT = 40;
byte TramaSerie[TRAMA_LENGTH];
short int Puntero;
boolean PrintWear, PrintFlat;

TM1638 module(DATA_PIN, CLOCK_PIN, STROBE_PIN);

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

void loop()
{
  ReadSerial();
  
  ModoAuto();  
}

void ModoAuto()
{
  FlatMessage = "Flat";
  TyreMesage = "tyrE";
  PrintWear = false;
  PrintFlat = false;

  MuestraOtrosValores();
  
  TyreManagement();
}

void ReadSerial()
{
  if (Serial.available() > 0)
  {
    if (Serial.available() > TRAMA_LENGTH)
    {
      Puntero = 0;
      memset(TramaSerie, 0, sizeof(TramaSerie));
      TramaSerie[Puntero] = Serial.read();
      if (TramaSerie[Puntero] == 0xFF)
      {
        for (Puntero = 1; Puntero < TRAMA_LENGTH; Puntero++)
        {
          TramaSerie[Puntero] = Serial.read();
        }
      }
    }
  }
}

void MuestraOtrosValores()
{
	//Aquí muestro otra información, en principio esto si funciona.	
}

void TyreManagement()
{
  if (TramaSerie[10] == WEAR_LIMIT)
  {
    TyreMesage.concat("1");
    PrintWear = true;
  }

  if (TramaSerie[11] == WEAR_LIMIT)
  {
    TyreMesage.concat("2");
    PrintWear = true;
  }

  if (TramaSerie[12] == WEAR_LIMIT)
  {
    TyreMesage.concat("3");
    PrintWear = true;
  }

  if (TramaSerie[13] == WEAR_LIMIT)
  {
    TyreMesage.concat("4");
    PrintWear = true;
  }

  if (PrintWear == true)
  {
    PrintMessage(TyreMesage);
    PrintWear = false;
  }

  if (TramaSerie[14] == 1)
  {
    PrintFlat = true;
    FlatMessage.concat("1");
  }

  if (TramaSerie[15] == 1)
  {
    PrintFlat = true;
    FlatMessage.concat("2");
  }

  if (TramaSerie[16] == 1)
  {
    PrintFlat = true;
    FlatMessage.concat("3");
  }

  if (TramaSerie[17] == 1)
  {
    PrintFlat = true;
    FlatMessage.concat("4");
  }

  if (PrintFlat == true)
  {
    PrintMessage(FlatMessage);
    PrintFlat = false;
  }
}

void PrintMessage(String text)
{
  module.setDisplayToString("        ", 0);
  module.setDisplayToString(text, 0, 0);
  delay(3000);
  module.setDisplayToString("        ", 0);
}

Como podéis ver, el código es sencillo, los mensajes de tipo “Flat” nunca deberían de verse porque el buffer envía un cero, sin embargo si que funciona con el mensaje tipo “Tyre”, estos no se visualizan, y si cambio el buffer del 10 al 12 por un 40 si se muestran, pero en ningún caso funciona correctamente con los valores del 14 al 17.

Solo se me ocurre que no se cargue bien el buffer en el metodo ReadSerial, el envío se realiza cada 50 milisegundos, pero eso no debería ser un problema, creo…

(Serial.available() > TRAMA_LENGTH)

Y si ambos son iguales entonces no cuenta?

Para leer un conjunto de bytes, puedes ahorrarte una sentencia for de esta manera:

Serial.readBytes(values, TRAMA_LENGTH);

PD: eso de que si el primer byte es igual a 255 o no, no lo tengo claro.
Y por cierto, puede que 9600 bps sea muy lento para 50 milisegundos.

Feliz año y muchas gracias! Te contesto.

Lucario448:

(Serial.available() > TRAMA_LENGTH)

Y si ambos son iguales entonces no cuenta?

Para leer un conjunto de bytes, puedes ahorrarte una sentencia for de esta manera:

Serial.readBytes(values, TRAMA_LENGTH);

Estoy reutilizando un código de terceras personas, probaré con eso que dices.

PD: eso de que si el primer byte es igual a 255 o no, no lo tengo claro.
Y por cierto, puede que 9600 bps sea muy lento para 50 milisegundos.

Bueno, como digo estoy reutilizando codigo, en el buffer que envío, la primera posición siempre es

buffer[0] = byte.MaxValue;

De momento voy a ver si hago que funcione y luego lo intentaré optimizar.

Respecto a la velocidad, en todos los ejemplos que he visto lo configuran a 9600 bps y por eso está así, si puedo poner mas velocidad no tengo ningún problema en cambiarlo.

Haciendo cálculos: sabes que el puerto serial UART está configurado como 8N1 (8 bits o un byte de datos, un bit de parada, sin paridad), entonces en realidad son 11 bits por byte (siempre hay dos bits de inicio).

Ahora: 9600 / 11 = 872.72 B/s (bytes por segundo); o 1.14 bytes por milisegundo (877 microsegundos por byte)
Enviar 34 bytes tarda 34 * 0.88 = 29.92 milisegundos.

30 milisegundos por cada 34 bytes que se reciben; sumado al tiempo que se tarda entre copiar los bytes entre búfer y otro, y procesar la información; posiblemente ahí es donde se excede el margen de 50 milisegundos.

He configurado el puerto a 115200 bps pero sigue mostrando el mensaje de texto cuando no debería, ya que en las posiciones del array del 14 al 17 siempre envío cero (En producción si podrá cambiar ese valor, pero de momento no).

No se si el problema es de sincronización entre dispositivos, funciona la sentencia flush()? En teoría lo que hace es esperar a que el buffer se cargue, no?

Y por otro lado, a ver si he interpretado bien, la carga del array que me has aconsejado:

void ReadSerial()
{
  if (Serial.available() > 0)
  {
    Serial.readBytes(TramaSerie, TRAMA_LENGTH);
Serial.flush();
  }
}

He configurado el puerto a 115200 bps pero sigue mostrando el mensaje de texto cuando no debería, ya que en las posiciones del array del 14 al 17 siempre envío cero (En producción si podrá cambiar ese valor, pero de momento no).

No se si el problema es de sincronización entre dispositivos, funciona la sentencia flush()? En teoría lo que hace es esperar a que el buffer se cargue, no?

Y por otro lado, a ver si he interpretado bien, la carga del array que me has aconsejado:

void ReadSerial()
{
  if (Serial.available() > 0)
  {
    Serial.readBytes(TramaSerie, TRAMA_LENGTH);
Serial.flush();
  }
}

--Edit--

Edito que estoy haciendo mas pruebas,

Al parecer empieza ha hace cosas raras cuando muestro mensajes en pantalla, si comento las lineas de código que llaman a la función TyreManagement y solo dejo una función en el loop funciona bien, si meto dos funciones, una después de otra en el loop es cuando ya empieza a fallar, no se muy bien como depurar con el IDE, pero tiene pinta de que no inicializa bien el buffer, he probado con esto pero se comporta igual

void ReadSerial2()
{
  if (Serial.available() > 0)
  {
    memset(TramaSerie, 0, sizeof(TramaSerie));
    Serial.readBytes(TramaSerie, TRAMA_LENGTH);
  }
}

La prueba que he hecho es pausar el Visual Studio para que la posicion 14 del array sea uno, mientras no cambie esa variable funciona bien, cuando la cambio a uno, el display muestra correctamente el mensaje pero ya deja de funcionar, no borra el mensaje y es como si la trama de bits se desconfigurase, intentaré hacer un vídeo del comportamiento.