Go Down

Topic: [Solucionado] Como puedo guardar una trama CAN en una variable (Read 2453 times) previous topic - next topic

JoseGD

Buenas a todos

Estoy estudiando un poco la comunicación CAN con arduino, estoy usando este ejemplo de las librerias,
En en cual veo todas las tramas que leo desde una maquina.

Pero me surge una duda haber si ustedes me la pueden resolver, viendo el código creo que las tramas que lee las guarda en las variable unsigned char len y buf.


Entonces como puede hacer que me guarde las tramas de cada ID en diferentes bufer, para después gestionarlas a mi manera:


Gracias

Las tramas que capturo son estas:


ID            Len    data

14EFE100   8     03 0A 17 00 20 00 10 00

14EFE101   8     01 53 12 00 20 05 00 0A

14EFE102   8     01 51 12 00 BA 00 03 00

14EFE103   8     01 53 12 00 2B 00 00 01

Code: [Select]

#include <SPI.h>
#include "mcp_can_Err.h"


const int SPI_CS_PIN = 10;

MCP_CAN CAN(SPI_CS_PIN);                                  

unsigned char len = 0;
unsigned char buf[8];

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

START_INIT:

    if(CAN_OK == CAN.begin(CAN_500KBPS))                  
    {
        Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println("Init CAN BUS Shield again");
        delay(100);
        goto START_INIT;
    }
}


void loop()
{
    

    if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
    {
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

        unsigned long canId = CAN.getCanId();
        
        Serial.println("-----------------------------");
        Serial.print("get data from ID: ");
        Serial.println(canId, HEX);

        for(int i = 0; i<len; i++)    // print the data
        {
            Serial.print(buf[i]);
            Serial.print("\t");
        }
        Serial.println();
    }
}


arkarash

Una forma rápida y sencilla sería crear una matriz doble (n,3) posiciones donde n es un contador de señales entrantes y los 3 datos a guardar de cada posición sería ID, LEN y DATA, recomiendo exportar a un SD si los datos son importantes o desbordarás rápido la memoria.

JoseGD

Gracias arkarash por la rápida respuesta, voy a intentar buscar un ejemplo de lo que me dice para entenderlo.

En principio solo me haría falta guardar los datos del DATA, pero de una manera ordenada.

Por ejemplo esta trama:

14EFE100   8     03 0A 17 00 20 00 10 00

Yo lo que quiero hacer es. Si la ID es 14EFE100 los datos de esta ID se guarden el la variable Nº1

Por que a la hora de enviarlos otra vez por CAN, seria asín :

CAN.sendMsgBuf (0xID, 0, 8, variable Nº1)

Con lo cual solo me hace falta guardar los datos, la ID y el LEN ya se lo puedo poner manualmente.





arkarash

Lo primero es saber si vas a querer guardar 4 o 4000 líneas de datos en la base de datos. Es importante para saber si lo guardas en un fichero externo o en una variable.

Si es en una variable te aconsejo crear una estructura:

Code: [Select]
struct DATACAN
   { unsigned long ID ; // ID del CAN
      unsigned char len ;       // Longitud
      unsigned char buf[8] data ;       // Data
   } ;


Luego accederías crearías una variable

Code: [Select]
DATACAN variable [10];

Y luego para acceder a los datos

Code: [Select]
Serial.println(variable [1].ID) ;

Más o menos y sin mirar si me he equivocado en algo, estudia un poco más del tema y si tienes alguna duda pregunta.

Enlace para consulta

JoseGD

La idea es la siguiente. La maquina genera 20 tramas can, las cuales las quiero guardar  y después  enviar a mi gusto cambiado la ID de la trama.

Por eso me hace falta saber  los Datos guardados en una variable a que ID corresponden.

Porque luego yo mandare eso datos cambiando la ID

EJ:

Esta trama

14EFE101   8     01 53 12 00 20 05 00 0A

Yo ahora la quiero mandar con la ID 15FFF201, pero eso mismos datos de esa ID lo mismo dentro de un dia los tengo que mandar con la IDXXXXXX

Voy ha estudiar lo que me mandas

Gracias




JoseGD

#5
May 07, 2020, 06:10 pm Last Edit: May 07, 2020, 06:11 pm by JoseGD
Buenas, he estado leyendo lo de las estructuras y no parece difícil, pero quería ver como puedo guardar los datos leído dependiendo de la ID de la trama, así que hice este codigo para probar antes de liarme con la estructura.

Pero no me funciona, no logro guardar los datos de la trama, use switch para saber que ID esta leyendo.

Alguna sugerencia.

Gracias

Code: [Select]


#include <SPI.h>
#include "mcp_can_Err.h"

const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN);


unsigned char len1 = 0;
unsigned char buf1[8];
unsigned char len2 = 0;
unsigned char buf2[8];
unsigned char len3 = 0;
unsigned char buf3[8];

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

START_INIT:

  if (CAN_OK == CAN.begin(CAN_500KBPS))                  // init can bus : baudrate = 500k
  {
    Serial.println("CAN BUS Shield init ok!");
  }
  else
  {
    Serial.println("CAN BUS Shield init fail");
    Serial.println("Init CAN BUS Shield again");
    delay(100);
    goto START_INIT;
  }
}


void loop() {

  CAN_MSGAVAIL == CAN.checkReceive();

  switch (CAN.getCanId()) {
    case 0x14EFE100:
      CAN.readMsgBuf(&len1, buf1);
      for (int i = 0; i < len1; i++)
      {
        Serial.print(buf1[i]);
        Serial.print("\t");
      }
      break;

    case 0x14EFE101:
      CAN.readMsgBuf(&len2, buf1);
      for (int i = 0; i < len2; i++)
      {
        Serial.print(buf2[i]);
        Serial.print("\t");
      }
      break;

    case 0x14EFE102:
      CAN.readMsgBuf(&len3, buf3);
      for (int i = 0; i < len3; i++)
      {
        Serial.print(buf3[i]);
        Serial.print("\t");
      }
      break;
  }
}


_jose_

#6
May 07, 2020, 07:07 pm Last Edit: May 07, 2020, 07:19 pm by _jose_
El codigo que pones no tiene nada que ver con el que tu mismo posteaste mas arriba,que supongo es el ejemplo de la libreria y es el "bueno".Esto:
Code: [Select]
CAN_MSGAVAIL == CAN.checkReceive();
no es lo mismo que esto:
Code: [Select]
if(CAN_MSGAVAIL == CAN.checkReceive())
La lectura de una trama debe estar condicionada a que haya algo que leer.
Aqui y segun el ejemplo ,getCanId() devuelve un unsigned long:
Code: [Select]
unsigned long canId = CAN.getCanId();
Sin embargo tu comparas con un hexadecimal:
Code: [Select]
case 0x14EFE100:
y esto no se si es correcto.
Edito porque acabo de hacer la prueba y se puede comparar.
Mira de poner Serial.println a modo de logs para ver los valores que recoges,por ejemplo una vez que compruebes que hay datos disponibles:
Code: [Select]
unsigned long canId = CAN.getCanId();
Serial.println(canId,HEX);

arkarash

No estas usando las estructuras por ningún sitio en el código pero bueno, si este código funcionase sólo guardarías el último dato de cada ID, los demás se machacarían.

Aparte de eso, comprueba que el switch case funciona bien que, creo que no con el 0x14EFE100 como condición, tu que has ejecutado el programa ¿entra en el case? ¿imprime por el puerto serial lo que debe? Si no imprime en el serial es que no entra en el case y podría ser por la condicion.

Edit: Como te han dicho más arriba el problema es que no entra en los case por la condicion

_jose_

Quote
Edit: Como te han dicho más arriba el problema es que no entra en los case por la condicion
No,lo acabo de comprobar y si que se puede comparar.

JoseGD

arkarash no usado aun las estructuras por que quería primero saber como guardar los dato según la ID, pero las usare cuando resuelva este problema y te agradezco mucho tu ayuda.

Mira _jose_ si este comando lo saco del  switch

Code: [Select]


CAN.readMsgBuf(&len, buf);



Y solo creo una variable para LEN y DATA, si funciona y veo los datos por el puerto serie

Code: [Select]

unsigned char len = 0;
unsigned char buf[8];


El codigo quedaria asin, mas o menos asin:

Code: [Select]


unsigned char len = 0;
unsigned char buf[8];


void loop() {

  CAN_MSGAVAIL == CAN.checkReceive();

  CAN.readMsgBuf(&len, buf);

  switch (CAN.getCanId()) {
    case 0x14EFE100:
 
      for (int i = 0; i < len; i++) // print the data
      {
        Serial.print(buf[i]);
        Serial.print("\t");
      }
      break;

    case 0x14EFE101:
   
      for (int i = 0; i < len; i++) // print the data
      {
        Serial.print(buf[i]);
        Serial.print("\t");
      }
      break;

    case 0x14EFE102:
     
      for (int i = 0; i < len; i++) // print the data
      {
        Serial.print(buf[i]);
        Serial.print("\t");
      }
      break;
  }
}





Pero no es lo que yo pretendo hacer, yo lo que quiero hacer es esto, mas o menos.
En este ejemplo lo que hago es capturar una trama con una ID y lanzar esa misma trama con una ID diferente y funciona perfectamente.

Code: [Select]

case 0x14EFE101:
     for (int i = 0; i < len; i++) {
     Serial.print(buf[i], HEX);
     Serial.print("\t");
     CAN.sendMsgBuf(0x15FEE103, 1, 8, buf);
     }
     Serial.println();
     break;


El problema esta en que no se como meter en cada variable los datos da cada ID para luego mandarlos con otra ID que yo quiera.
Por eso hice la prueba del post de arriba, y pensé si leo La IDXXXXXX que me guarde los datos en una Variable "Y" y después poder lanzarla con este comando:

Code: [Select]


CAN.sendMsgBuf(0x15FEE103, 1, 8, Variable Y);



Gracias a los dos por la ayuda.






_jose_

Desconozco esa libreria y que tipo de parametros hay que pasar,deduzco que son arrays de bytes.si sabes cuales son los 20 Id y las 20 tramas ,podrias probar algo como esto ,pero no se si funcionara:
Code: [Select]

#define ID1 0x15FEE103
#define ID2 0x14EFE101
// Asi hasta los 20
#define TRAMA1 0x015312002005000A
#define TRAMA2 0x0153180F2006000A
// Asi hasta los 20
void setup(){ // Codigo que sea....}
void loop(){
// Quiero enviar ID1 con TRAMA2
  CAN.sendMsgBuf(ID1, 1, 8, TRAMA2);
}
 

arkarash

arkarash no usado aun las estructuras por que quería primero saber como guardar los dato según la ID, pero las usare cuando resuelva este problema y te agradezco mucho tu ayuda.

Mira _jose_ si este comando lo saco del  switch

Code: [Select]


CAN.readMsgBuf(&len, buf);



Y solo creo una variable para LEN y DATA, si funciona y veo los datos por el puerto serie

Code: [Select]

unsigned char len = 0;
unsigned char buf[8];


El codigo quedaria asin, mas o menos asin:

Code: [Select]


unsigned char len = 0;
unsigned char buf[8];


void loop() {

  CAN_MSGAVAIL == CAN.checkReceive();

  CAN.readMsgBuf(&len, buf);

  switch (CAN.getCanId()) {
    case 0x14EFE100:
 
      for (int i = 0; i < len; i++) // print the data
      {
        Serial.print(buf[i]);
        Serial.print("\t");
      }
      break;

    case 0x14EFE101:
   
      for (int i = 0; i < len; i++) // print the data
      {
        Serial.print(buf[i]);
        Serial.print("\t");
      }
      break;

    case 0x14EFE102:
     
      for (int i = 0; i < len; i++) // print the data
      {
        Serial.print(buf[i]);
        Serial.print("\t");
      }
      break;
  }
}





Pero no es lo que yo pretendo hacer, yo lo que quiero hacer es esto, mas o menos.
En este ejemplo lo que hago es capturar una trama con una ID y lanzar esa misma trama con una ID diferente y funciona perfectamente.

Code: [Select]

case 0x14EFE101:
     for (int i = 0; i < len; i++) {
     Serial.print(buf[i], HEX);
     Serial.print("\t");
     CAN.sendMsgBuf(0x15FEE103, 1, 8, buf);
     }
     Serial.println();
     break;


El problema esta en que no se como meter en cada variable los datos da cada ID para luego mandarlos con otra ID que yo quiera.
Por eso hice la prueba del post de arriba, y pensé si leo La IDXXXXXX que me guarde los datos en una Variable "Y" y después poder lanzarla con este comando:

Code: [Select]


CAN.sendMsgBuf(0x15FEE103, 1, 8, Variable Y);



Gracias a los dos por la ayuda.






A ver, creo que _Jose_ no te ha entendido o no te he entendido yo.

Si funciona con el CAN.Receive fuera del switch déjalo fuera, de hecho es donde debería estar, guardas en variables "temporales" ID, len y buf[8], creas la estructura y haces el switch case para almacenarla. Yo es que lo veo claro así, pero es un enfoque diferente del que le da _Jose_

JoseGD

Quote
Desconozco esa libreria y que tipo de parametros hay que pasar,deduzco que son arrays de bytes.si sabes cuales son los 20 Id y las 20 tramas ,podrias probar algo como esto ,pero no se si funcionara:
Code: [Select]


#define ID1 0x15FEE103
#define ID2 0x14EFE101
// Asi hasta los 20
#define TRAMA1 0x015312002005000A
#define TRAMA2 0x0153180F2006000A
// Asi hasta los 20
void setup(){ // Codigo que sea....}
void loop(){
// Quiero enviar ID1 con TRAMA2
  CAN.sendMsgBuf(ID1, 1, 8, TRAMA2);
}
 
Esto no funcionaria _jose_ ya que simpre mandaria en caso de la trama 1 015312002005000A y no seria correcto, pues la trama va cambiando, me explico la que yo capturo de la maquina son esos valores, pero en van variando constantemente y si yo solo mando es array no funcionara, por eso lo de guardarla con sus respectivos cambio, no se si m he explicado,

JoseGD

Quote
A ver, creo que _Jose_ no te ha entendido o no te he entendido yo.

Si funciona con el CAN.Receive fuera del switch déjalo fuera, de hecho es donde debería estar, guardas en variables "temporales" ID, len y buf[8], creas la estructura y haces el switch case para almacenarla. Yo es que lo veo claro así, pero es un enfoque diferente del que le da _Jose_

arkarash entiendo lo que dices, pero no entiendo como hago para guardar en variables los Datos de cada ID, ya que este comado
Code: [Select]

CAN.readMsgBuf(&len, buf);


Lee todo a la vez y guarda los datos en

Code: [Select]

unsigned char len = 0;
unsigned char buf[8];


No entiendo o no lo veo como hago para separa los datos de cada ID en una variable.

Gracias

arkarash

Buenas, no te había aclarado esa parte porque me habías dicho que controlabas las estructuras.

Creas la estructura:

Code: [Select]
typedef struct
   { unsigned long ID ; // ID del CAN
      unsigned char len ;       // Longitud
      unsigned char [8] data ;       // Data
   } DATACAN;


Luego lees como ya sabes y se almacena en las variables, y después se almacena en la estructura:

Code: [Select]
DATACAN Datos [20] ;
Datos[a].ID = ID ;
Datos[a].len = len ;
For ....{
Datos[a].data [i]= buf[i] };
a++ ;


Espero que esto resuelva tus dudas

Go Up