[Solucionado] Mandar trama dentro de switch case, no me funciona.

Buenas a todos, tengo un problema con mi código, en si es muy simple, por el puerto serie envió un dato y enciendo leds o mando una trama CAN.

El problema lo tengo cuando lanzo la trama CAN, ya que la tengo metida dentro de un case y claro si mando el dato, envía la trama una sola vez, por que ya se encuentra con el brake.

Como puedo hacer que la trama la envié hasta que yo quiera o en este caso hasta que reciba el dato:

case 's':
     CAN.sleep();                     // Apagmos el CAN
     break;

He usado switch case porque este es solo el principio del programa y tendra muchos led mas que encender y al menos 10 tramas mas.

Gracias

#include <mcp_can.h>
#include <SPI.h>

int led1 = 9;
int led2 = 11;
int led3 = 7;
int led4 = 8;
int led5 = 3;
int led6 = 5;

char dato;

// declaramos el pin 10 como CS para el procesador CAN
const int SPI_CS_PIN = 10;
MCP_CAN CAN(SPI_CS_PIN);

///////////////// Trama CAN1

unsigned char a[4] = {0x20, 0x09, 0x00, 0x00};
unsigned char b[8] = {0x00, 0x12, 0x00, 0xFF, 0x30, 0x5E, 0x2F, 0x00};
unsigned char c[8] = {0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char d[7] = {0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char e[8] = {0x00, 0x74, 0x32, 0x10, 0x31, 0x20, 0x3D, 0x02};
unsigned char f[8] = {0x3D, 0x00, 0x11, 0x45, 0x00, 0x00, 0x06, 0x00};

///////////// Trama CAN2

unsigned char M1[8] = {0xC8, 0x28, 0xA8, 0x5A, 0x14, 0x14, 0xA8, 0x85};
unsigned char M2[8] = {0xF1, 0x26, 0x0E, 0x88, 0xF0, 0x2B, 0x60, 0x1C};
unsigned char M3[8] = {0x90, 0x03, 0x00, 0x00, 0x00, 0x01, 0x54, 0x00};
unsigned char M4[8] = {0x18, 0x26, 0x00, 0x00, 0x20, 0x51, 0x0F, 0x71};

////////////// Trama CAN3

unsigned char R3[8] = {0xCE, 0x03, 0xA5, 0x40, 0x14, 0xA8, 0x56, 0x85};
unsigned char R4[8] = {0x90, 0x03, 0x00, 0x00, 0x00, 0x01, 0x54, 0x00};
unsigned char R5[8] = {0x18, 0x06, 0xA8, 0x00, 0x20, 0x51, 0x0F, 0x70};


///////////// Trama CAN4

unsigned char C1[8] = {0x80, 0x03, 0x00, 0x00, 0x04, 0x01, 0x50, 0x00};
unsigned char C2[4] = {0x65, 0x10, 0x1D, 0x01};
unsigned char C3[8] = {0x80, 0x03, 0x00, 0x00, 0x04, 0x01, 0x50, 0x00};
unsigned char C4[3] = {0x00, 0xFF, 0XFF};
unsigned char C5[8] = {0x08, 0x16, 0x00, 0x00, 0x33, 0x52, 0x02, 0x01};
unsigned char C6[4] = {0x82, 0x00, 0xDD, 0x11};
unsigned char C7[4] = {0x53, 0x94, 0x04, 0x00};
unsigned char C8[4] = {0x18, 0x10, 0x80, 0x83};
unsigned char C9[5] = {0x02, 0x85, 0x54, 0xA0, 0x81};
unsigned char C10[6] = {0x7F, 0xAB, 0x7F, 0xFF, 0x50, 0x07};
unsigned char C11[7] = {0x52, 0x2F, 0x6A, 0x80, 0xFE, 0x02, 0x00};
unsigned char C12[5] = {0x31, 0x31, 0x5E, 0x00, 0x10};
unsigned char C13[8] = {0x1B, 0xED, 0x38, 0x10, 0x31, 0x28, 0x3D, 0x02};
unsigned char C14[5] = {0x22, 0x00, 0x1B, 0xE4, 0x0A};
unsigned char C15[1] = {0x00};
unsigned char C16[7] = {0x00, 0x8F, 0x75, 0xBF, 0xB5, 0xE3, 0x0B};
unsigned char C17[2] = {0x04, 0x01};
unsigned char C18[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00};
unsigned char C19[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x18};
unsigned char C20[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x19};
unsigned char C21[5] = {0xC8, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char C22[6] = {0x04, 0x63, 0xFF, 0x3C, 0x18, 0x85};

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

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);

}

void loop() {
  if (Serial2.available())
  {
    dato = Serial2.read();
  }
  switch (dato) {

    case 'a':
      digitalWrite(led1, LOW);
      break;

    case 'b':
      digitalWrite(led1, HIGH);
      break;

    case 'c':
      digitalWrite(led2, LOW);
      break;

    case 'd':
      digitalWrite(led2, HIGH);
      break;

    case 'e':
      digitalWrite(led3, LOW);
      break;

    case 'f':
      digitalWrite(led3, HIGH);
      break;

    case 'g':
      digitalWrite(led4, LOW);
      break;

    case 'h':
      digitalWrite(led4, HIGH);
      break;

    case 'j':
      digitalWrite(led5, LOW);
      break;

    case 'k':
      digitalWrite(led5, HIGH);
      break;

    case 'l':
      digitalWrite(led6, LOW);
      break;

    case 'm':
      digitalWrite(led6, HIGH);
      break;

    case 'n':

      CAN_OK == CAN.begin(CAN_500KBPS);
      CAN.sendMsgBuf(0x625, 0, 4, a);         // Lanzamos CAN1
      CAN.sendMsgBuf(0x60D, 0, 8, b);
      CAN.sendMsgBuf(0x35D, 0, 8, c);
      CAN.sendMsgBuf(0x551, 0, 7, d);
      CAN.sendMsgBuf(0x181, 0, 8, e);
      CAN.sendMsgBuf(0x354, 0, 8, f);
      break;

    case 'o':

      CAN_OK == CAN.begin(CAN_500KBPS);
      CAN.sendMsgBuf(0x350, 0, 8, M1);         // Lanzamos CAN2
      CAN.sendMsgBuf(0x5DE, 0, 8, M2);
      CAN.sendMsgBuf(0x35D, 0, 8, M3);
      CAN.sendMsgBuf(0x60D, 0, 8, M4);
      break;

    case 'p':
      CAN_OK == CAN.begin(CAN_500KBPS);    // Lanzamos CAN3
      CAN.sendMsgBuf(0x350, 0, 8, R3);
      CAN.sendMsgBuf(0x35D, 0, 8, R4);
      CAN.sendMsgBuf(0x60D, 0, 8, R5);
      break;

    case 'r':

      CAN_OK == CAN.begin(CAN_500KBPS);
      CAN.sendMsgBuf(0x35D, 0, 8, C1);         // Lanzamos CAN4
      CAN.sendMsgBuf(0x215, 0, 4, C2);
      CAN.sendMsgBuf(0x5C5, 0, 8, C3);
      CAN.sendMsgBuf(0x645, 0, 3, C4);
      CAN.sendMsgBuf(0x60D, 0, 8, C5);
      CAN.sendMsgBuf(0x625, 0, 4, C6);
      CAN.sendMsgBuf(0x505, 0, 4, C7);
      CAN.sendMsgBuf(0x581, 0, 4, C8);
      CAN.sendMsgBuf(0x500, 0, 5, C9);
      CAN.sendMsgBuf(0x0C2, 0, 6, C10);
      CAN.sendMsgBuf(0x551, 0, 7, C11);
      CAN.sendMsgBuf(0x161, 0, 5, C12);
      CAN.sendMsgBuf(0x181, 0, 8, C13);
      CAN.sendMsgBuf(0x1F9, 0, 5, C14);
      CAN.sendMsgBuf(0x5E4, 0, 1, C15);
      CAN.sendMsgBuf(0x511, 0, 7, C16);
      CAN.sendMsgBuf(0x651, 0, 2, C17);
      CAN.sendMsgBuf(0x354, 0, 8, C18);
      CAN.sendMsgBuf(0x284, 0, 8, C19);
      CAN.sendMsgBuf(0x285, 0, 8, C20);
      CAN.sendMsgBuf(0x2A0, 0, 5, C21);
      CAN.sendMsgBuf(0x715, 0, 6, C22);
      break;

    case 's':
      CAN.sleep();                     // Apagmos el CAN
      break;

  }
}

Buenas, he pensado que si hago un bucle while y trama no dejara de enviarse, pero si hago esto, como para el while?

 case 'n':
      while (true) {
        CAN_OK == CAN.begin(CAN_500KBPS);
        CAN.sendMsgBuf(0x625, 0, 4, a);         // Lanzamos CAN1
        CAN.sendMsgBuf(0x60D, 0, 8, b);
        CAN.sendMsgBuf(0x35D, 0, 8, c);
        CAN.sendMsgBuf(0x551, 0, 7, d);
        CAN.sendMsgBuf(0x181, 0, 8, e);
        CAN.sendMsgBuf(0x354, 0, 8, f);
      }
      break;

¿Pero entre que dispositivos mandas esa trama?¿ Tienes posibilidad en el dispositivo de destino de implementar algun tipo de respuesta que confirme que se han recibido los datos?

No el dispositivo donde lanza la trama no tiene posibilidad de enviar ningún dato, es una maquina que depende de la trama que le mande hace cosas diferente, por ejemplo la primera trama la maquina coge el paquete y lo embala entero con un precinto, y asín va haciendo cosas diferentes,

En verdad no estoy haciendo ningún proyecto, solo estudiando la programación y me encontré son ese problema.

Con el bucle while funciona, pero no tengo forma de pararlo.

Si te entendido bien,¿lo que quieres es que una vez dada la orden de mandar la trama,siga enviandose repetidamente hasta que la canceles?
Si es asi ,una posible solucion seria encapsular el envio de la trama en una funcion y definir una variable booleana que un principio tiene el valor false,pero al recibir el caracter de inicio de trama se cambia a true,entonces la ejecucion de la funcion estara condicionada a esa variable:

boolean ejecutarTrama = False;

void enviarTrama(){
        CAN_OK == CAN.begin(CAN_500KBPS);
        CAN.sendMsgBuf(0x625, 0, 4, a);         // Lanzamos CAN1
        CAN.sendMsgBuf(0x60D, 0, 8, b);
        CAN.sendMsgBuf(0x35D, 0, 8, c);
        CAN.sendMsgBuf(0x551, 0, 7, d);
        CAN.sendMsgBuf(0x181, 0, 8, e);
        CAN.sendMsgBuf(0x354, 0, 8, f);
}

void Setup(){
// etc,etc
}
void Loop(){
  if(ejecutarTrama) {
    enviarTrama()
  }
  //etc, etc
  case 'n':
     ejecutarTrama = True;
  break;
  case 's':
     CAN.sleep();
     ejecutarTrama = False;
     break;

Esta escrito al vuelo sin editor y puede tener fallos pero es para que veas la idea

OK, lo entiendo perfectamente.

Mañana lo probare y te cuanto.

Muchas gracias

Buenas Jose, acabo de probar tu sugerencia y funciona perfectamente, creare una variable booleana por cada trama un if y listo.

La sentencia if la haré con if y luego else if, no ? para que valla mas fluido el codigo.

Gracias

Podria ser una solucion si no hay muchas tramas,si no ,el codigo puede empezar a complicarse.En cuanto a lo del if,no se cuanto mas rapido seria una opcion u otra.Si es cierto que evaluando opciones en las que solo una opcion puede ser cierta ,con else if en el momento que una se cumple sale de la evaluacion ,con if separados siempre los evaluaria todos,hay un ahorro de tiempo con la primera opcion.Tambien puedes volver a usar un switch.

En principio serian unas 10 tramas.

Lo que no entiendo es como hacer un Switch si voy a tener variables boolenas diferentes.

Como lo hago?

boolean ejecutarTrama = false;
boolean ejecutarTrama1 = false;
boolean ejecutarTrama2 = false;


void enviarTrama(){

// TRAMA 0
        
}

void enviarTrama1(){

// TRAMA 1
        
}

void enviarTrama2(){

// TRAMA 2
        
}



void Setup(){
// etc,etc
}
void Loop(){

  if(ejecutarTrama) {
    enviarTrama()
  }

else  if(ejecutarTrama1) {
    enviarTrama()1
  }

else  if(ejecutarTrama2) {
    enviarTrama()2
  }



  //etc, etc
  case 'n':
     ejecutarTrama = True;
  break;

  case 'o':
     ejecutarTrama1 = True;
  break;

  case 'p':
     ejecutarTrama2 = True;
  break;

  case 's':
     CAN.sleep();
     ejecutarTrama = False;
     ejecutarTrama1 = False;
     ejecutarTrama2 = False;
     break;
int numeroTrama;
boolean ejecutandoTrama = false;

void enviarTrama1(){
// TRAMA 1
}

void enviarTrama2(){
// TRAMA 2
}

void enviarTrama3(){
// TRAMA 3
}


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  if(ejecutandoTrama){
    switch (numeroTrama) {
      case 1 :
         enviarTrama1();
      break;
      case 2 :
         enviarTrama2();
      break;
      case 3 :
         enviarTrama3();
      break;
    }
  }
}

//etc etc
  
switch(dato){
  case 'n':
     trama = 1;
     ejecutandoTrama = True;
  break;
  case 'o':
     trama = 2;
     ejecutandoTrama = True;
  break;
  case 'p':
  trama = 3;
     ejecutandoTrama = True;
  break;
  case 's':
     CAN.sleep();
     ejecutandoTrama = False;
     break;
}

Vale entiendo perfectamente la forma de hacerlo.

De esa forma que me explicas no habría problemas por aumentar el numero de tramas.

Lo pruebo mañana y te comento.

Muchas Gracias

Buenas Jose, lo he probado y funciona muy bien, lo probé con 8 tramas y va bastante bien.

Muchas gracias por tu ayuda.