Go Down

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

_jose_

#15
May 08, 2020, 01:57 pm Last Edit: May 08, 2020, 02:03 pm by _jose_
Bueno,espero que saques conclusiones ,cuanto mas preciso seas explicando tu proyecto ,menos mataremos moscas a cañonazos...De hecho sigo sin acabar de comprenderlo ,asi que hasta que no lo tenga claro yo me bajo aqui.

JoseGD

Bueno,espero que saques conclusiones ,cuanto mas preciso seas explicando tu proyecto ,menos mataremos moscas a cañonazos...De hecho sigo sin acabar de comprenderlo ,asi que hasta que no lo tenga claro yo me bajo aqui.
_jose_ creí que en el mensaje nº 4 lo explique, te pido disculpas si no lo hice bien, y agradezco muchísimo tu ayuda.

El proyecto es el siguiente, tengo una maquina industrial la cual genera 20 tramas CAN de 8 bytes cada una, estos bytes tiene información de temperatura, humedad, etc... e iran cambiado a medida que lanza la trama.

EL objetivo es leer y guardar los datos de cada ID y después lanzarlos a otra maquina modificando solo la ID de cada trama.

Los lanzare pulsando un teclado por ejemplo:

La ID 14FEE101 con sus datos, si pulso la tecla 'A' mando eso datos que estoy leyendo de esa ID pero cambiamos la direccion ID, lo mandaríamos ahora con 15FEE201 por ejemplo.

Te pido disculpas _jose_si te sentó mal que no me explicara bien.

Un Saludo

arkarash


JoseGD

Y mi respuesta te sirve o no?
Gracias arkarash por tu repuesta, la estaba estudiando ahora,  voy a hacer una pruebas y si no te importa, si me surge algun problema o duda te lo digo.

Gracias

_jose_

Quote
estos bytes tiene información de temperatura, humedad, etc... e iran cambiado a medida que lanza la trama.
Este era un detalle importante ,porque lo que yo entendi hasta ahora es que la maquina trabaja con 20 tramas iguales.En ese caso ya te han dado una solucion.

JoseGD

Buenas arkarash, llevo toda la tarde leyendo para entender bien las estructuras, pero no consigo implantarlo en el codigo.

He vito este video, que te lo eplica y el enlace que me mandaste, mas tu ejemplo.

https://www.youtube.com/watch?v=Qzq-lnO9dAc

Me comentabas que hiciera

 
Quote
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í
No entiendo esto:
Code: [Select]


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


Y por mas que he leído no veo como hacer el switch case para almacenarla en la estructura.

Voy a seguir estudiando, haber si llego a comprenderlo.

Gracias


JoseGD

Bueno he conseguido entenderlo un poco e hice este que en principio funciona
Code: [Select]

#include <SPI.h>
#include "mcp_can_Err.h"
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN);

typedef struct
{ unsigned long ID ;           // ID del CAN
  unsigned char len1;       // Longitud
  unsigned char data[8];       // Data
} DATACAN;

DATACAN Datos[20];

unsigned long canId;
unsigned char len = 0;
unsigned char buf[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() {

 Datos[8].ID = canId;
 Datos[2].len1 = len;
 Datos[8].data[8] = buf;


 if(CAN_MSGAVAIL == CAN.checkReceive())
 {

  CAN.readMsgBuf(&len, buf);
  canId = CAN.getCanId();

  Serial.println("-----------------------------");
  Serial.print("get data from ID: ");
  Serial.println(Datos[8].ID, HEX);

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



Supongo que tendré que crear mas comando como este, tantos como ID tengo, que serian 20, no?
Code: [Select]

DATACAN Datos[20];
DATACAN Datos1[20];
DATACAN Datos2[20];



Ahora me surge la duda de como hago con switch case para guardar cada trama con su ID.

No se si lo he echo bien o no.

arkarash

La idea es que Datos [1] sea una trama, Datos [2] otra...

Datos[1].ID
Datos[2].len
...

JoseGD

#23
May 10, 2020, 10:51 am Last Edit: May 10, 2020, 10:55 am by JoseGD
Entonces quedaría asín
Code: [Select]

 typedef struct
{ unsigned long ID ;              // ID del CAN
  unsigned char len1;             // Longitud
  unsigned char data[8];        // Data
} DATACAN;

DATACAN Datos[20];


Luego separa cada trama
Code: [Select]


  Datos[1].ID = canId;
  Datos[1].len1 = len;
  Datos[1].data[8] = buf;

  Datos[2].ID = canId;
  Datos[2].len1 = len;
  Datos[2].data[8] = buf;


Y por ultimo el Switch quedaría algo asín, no?
Code: [Select]


 switch (CAN.getCanId()) {
  
        case 0x14EFE100:
            
            buf[8] = Datos[1].data[8];

      break;
  
        case 0x14EFE101:
            
            buf[8] = Datos[2].data[8];

      break;
}



No se si era asin o me echo un poco de lio

Gracias

arkarash

El switch no se para que lo quieres no lo acabo de entender, lo que si te digo que para saber qué datos coger tienes que hacer un recorrido por todos los Datos[a].ID comparándolo con él resultado que buscas y cuando encuentres él que buscas usar el Datos[a].data

JoseGD

Buenas arkarash, como me dijiste esto

Quote
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
Pense que una vez creada la estructura, con el switch guardo cada buf y len con su ID, si no como hago para guardar cada trama en la variable.

Pense esto, que lo mismo esta mal asi:

Guardo con switch la trama en cada variable Dato y luego hago esto:
Code: [Select]

CAN.sendMsgBuf(0x15EFE105, 1, 8, Dato[a]);


Con este comando envió el buf guardado en Dato[a] con ID 14EFE100, pero le cambio la ID por 15EFE105, que es el objetivo mandar los datos de la trama cambiando la ID, que lo haría asin:
Code: [Select]


switch (teclado){

case '1':
 
CAN.sendMsgBuf(0x15EFE105, 1, 8, Dato[a]);

// aqui para que la trama no pare hare un false - true, eso lo tengo controlado

break;
}




Por favor, si ves que lo estoy haciéndolo mal, dímelo y explícame como lo puedo hacer y lo estudio, aunque ya con mi edad me cuesta entender las cosas, pero esfuerzo.

Muchas Gracias por la ayuda



JoseGD

Buenas a todos, pues nada no consigo guardar las tramas en las variable, se guardan datos pero sin sentido, he hecho la prueba con solo dos tramas.

Creo la estructura y las variables temporales
Code: [Select]

typedef struct
{ unsigned long ID ;           
  unsigned char len1;     
  unsigned char data[8];       
} DATACAN;

DATACAN Trama1;
DATACAN Trama2;

// Variables temporales
unsigned long canId;
unsigned char len = 0;
unsigned char buf[8];


El el loop hago esto:
Code: [Select]

  Trama1.ID = canId;
  Trama1.len1 = len;
  Trama1.data[8] = buf;

  Trama2.ID = canId;
  Trama2.len1 = len;
  Trama2.data[8] = buf;


Y despues con el Swtch intento guardar los datos de las tramas segun la ID que llegue a leer
Code: [Select]

case 0x15EFE105:
      buf[8] = Trama1.data[8];
     
      Serial.println("-----------------------------");
      Serial.print("get data from ID: ");
      Serial.println(Trama1.ID, HEX);
      for (int i = 0; i < len; i++)
      {
        Serial.print(Trama1.data[i], HEX);
        Serial.print("\t");
      }
      Serial.println();

      break;

    case 0x15EFE106:
      buf[8] = Trama2.data[8];
     
      Serial.println("-----------------------------");
      Serial.print("get data from ID: ");
      Serial.println(Trama1.ID, HEX);
      for (int i = 0; i < len; i++)
      {
        Serial.print(Trama2.data[i], HEX);
        Serial.print("\t");
      }
      Serial.println();

      break;
  }



Pero no funciona nada, los datos que guarda no tiene sentidos o se me estan mezclando.

Este es el código completo.
Code: [Select]

#include <SPI.h>
#include "mcp_can_Err.h"
const int SPI_CS_PIN = 9;

MCP_CAN CAN(SPI_CS_PIN);

typedef struct
{ unsigned long ID ;
  unsigned char len1;
  unsigned char data[8];
} DATACAN;

DATACAN Trama1;
DATACAN Trama2;

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

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


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() {

  Trama1.ID = canId;
  Trama1.len1 = len;
  Trama1.data[8] = buf;

  Trama2.ID = canId;
  Trama2.len1 = len;
  Trama2.data[8] = buf;


  CAN_MSGAVAIL == CAN.checkReceive();

  CAN.readMsgBuf(&len, buf);
  canId = CAN.getCanId();

  switch (CAN.getCanId()) {

    case 0x15EFE105:
      buf[8] = Trama1.data[8];
     
      Serial.println("-----------------------------");
      Serial.print("get data from ID: ");
      Serial.println(Trama1.ID, HEX);
      for (int i = 0; i < len; i++)
      {
        Serial.print(Trama1.data[i], HEX);
        Serial.print("\t");
      }
      Serial.println();

      break;

    case 0x15EFE106:
      buf[8] = Trama2.data[8];
     
      Serial.println("-----------------------------");
      Serial.print("get data from ID: ");
      Serial.println(Trama1.ID, HEX);
      for (int i = 0; i < len; i++)
      {
        Serial.print(Trama2.data[i], HEX);
        Serial.print("\t");
      }
      Serial.println();

      break;
  }
}


Yo creo que estoy haciendo todo mal, pero no lo veo.


Básicamente lo único que quiero guardar es los datos de cada trama, que no es mas que un array de 8 bytes.
Pero sabiendo que trama que guarde corresponde a cada IDXXXXXX.

Necesito una ayudita.

Gracias

_jose_

Puedes poner algun enlace a la maquina que estas usando o algun tipo de datasheet donde se pueda ver como funciona?Porque veo que haces cosas que no me cuadran ,pero no se decirte que haces mal porque desconozco su funcionamiento.
Por ejemplo:
Code: [Select]
void loop() {

  Trama1.ID = canId;
  Trama1.len1 = len;
  Trama1.data[8] = buf;

  Trama2.ID = canId;
  Trama2.len1 = len;
  Trama2.data[8] = buf;

¿Como estas asignado valores si la lectura se supone que la haces mas abajo?
Code: [Select]
CAN.readMsgBuf(&len, buf);
Ademas estas asignando el mismo valor a la variable Trama1 y  Trama2,¿Cuando cambian canId,len y buf???
¿Se solicita la informacion a la maquina con algun comando especifico o esta la envia cada determinado tiempo?
¿Envia las 20 tramas juntas?
En fin, informacion,informacion,informacion.......

JoseGD

Buenas _jose_ es que creo que no se hacer el código de las estructuras.

Mira te explico, es una maquina industrial la cual lleva una pantalla de telemetria (mañana intento hacerle una foto y te la pongo aquí), en esta pantalla vemos todos los datos, de varias temperaturas, posicionamiento de ejes, posición de la pieza donde esta situada, etc......lleva muchísimos sensores.

A la pantalla a parte de los cables de alimentación solo le llegan dos cables trenzados de CAN y esta pantalla solo admites las 20 ID que te muestro.

Para sacar esas tramas, he usado un arduino con un shield MCP2512  y el sketch que puse en el primer post, que es el ejemplo que viene en las libreas para capturas las tramas.

En estas tramas vemos una ID (extendida de 29 bits) y los datos que recibimos son 8 bytes, el LEN solo nos indica el numero de bytes de la trama, los datos de no paran de varias durante el funcionamiento de la maquina.

Code: [Select]

   ID    LEN           DATA
15EFE411  8   01 1C 20 00 1C 00 00 00
15EFE412  8   01 2C 1F 00 1C 00 00 00
15EFE413  8   01 21 1D 00 1D 00 00 00
15EFE414  8   01 21 1F 00 1D 00 00 00
15EFE415  8   01 53 12 00 20 00 00 00
15EFE416  8   01 AB 13 00 20 00 00 00
15EFE417  8   02 02 14 00 20 00 00 00
15EFE418  8   02 5A 15 00 20 00 00 00
15EFE419  8   02 B2 16 00 20 00 00 00
15EFE41A  8   03 0A 17 00 20 00 00 00
15EFE41B  8   03 62 18 00 20 00 00 00
15EFE41C  8   03 BA 19 00 20 00 00 00
15EFE41D  8   04 11 1A 00 20 00 00 00
15EFE41E  8   04 69 1B 00 20 00 00 00
15EFE41F  8   04 C1 1C 00 20 00 00 00
15EFE420  8   00 00 1D 00 20 00 00 00
15EFE421  8   00 4B 1E 00 20 00 00 00
15EFE422  8   00 A3 1F 00 20 00 00 00
15EFE423  8   00 FB 20 00 20 00 00 00
15EFE424  8   01 53 21 00 20 00 00 00



El problema, es que voy a cambiar la pantalla de telemetria por que esta está medio roto el display, y la pantalla nueva no admite esas ID ( lo que tiene las cosas chinas).
Esta pantalla admite solo de la 01800000 a  02000000.


Entonces el objetivo es leer esas 20 tramas y mandarlas a la nueva pantalla con las ID cambiadas.


Yo hice este Codigo para probar  mandar la trama cambiando la ID, lo que hice es mandar un dato por el puerto serie y al recibir el dato manda la trama  con la ID cambiada y funciona perfecto, pero claro si solo mando una trama en cuando hice la prueba mandando la segunda, se mezcla todo los datos, por que esta todo en el mismo bufer.

Code: [Select]

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

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

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

boolean ejecutandoTrama1 = false;
boolean ejecutandoTrama2 = false;

char dato;

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() {

  if (ejecutandoTrama1) {
    Trama1();
  }
  if (ejecutandoTrama2) {
    Trama2();
  }

  CAN_MSGAVAIL == CAN.checkReceive();          // check if data coming

  CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf

  switch (dato) {
    case '0':
      if (CAN.getCanId() == 0x15EFE411) {
        ejecutandoTrama1 = true;
      }
      break;

    case '1':
      if (CAN.getCanId() == 0x15EFE412) {
        ejecutandoTrama2 = true;
      }
      break;
  }
}

  void Trama1() {
    CAN.sendMsgBuf(0x01800001, 1, 8, buf);
  }

  void Trama2() {
    CAN.sendMsgBuf(0x01800002, 1, 8, buf);
  }



Por eso quiero guardar los datos de cada trama en variables diferentes, pero no se hacerlo para que funcione.

Si no entiendes algo, por favor dímelo.

Muchas Gracias

_jose_

#29
May 13, 2020, 08:19 pm Last Edit: May 13, 2020, 08:22 pm by _jose_
Ok ,y un enlace a la libreria que usas?
Code: [Select]
#include "mcp_can_Err.h"
Esto no cuadra ,es como si solo importaras una parte,es un nombre raro para una libreria.
Quote
los datos de no paran de varias durante el funcionamiento de la maquina.
osea los datos llegan de la maquina ,no se solicitan?

Go Up