Go Down

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

JoseGD

#30
May 13, 2020, 08:57 pm Last Edit: May 13, 2020, 09:02 pm by JoseGD
Aquí tienes las librerías _jose_, son unas que me pasaron que por lo que se ve están modificadas y corregidos algunos errores.

Quote
osea los datos llegan de la maquina ,no se solicitan?
Eso es jose, los datos llegan todos a la vez a la pantalla y listo, no hay comunicación bidireccional entre ellos.

Gracias

_jose_

Quote
Esta pantalla admite solo de la 01800000 a  02000000.
Entonces entiendo que a cada id de la pantalla rota se van a cambiar por otras 20 id diferentes compatibles con la pantalla nueva ,pero que siempre seran las mismas?Es decir ,cojo la idxxxxxxxxx y la envio como idzzzzzzzzzzz y siempre que reciba la idxxxxxxxx la mandare como idzzzzzzzzzz ?

JoseGD

Exacto _jose_ eso es lo que tengo que hacer.


_jose_

#33
May 13, 2020, 11:37 pm Last Edit: May 13, 2020, 11:51 pm by _jose_
A ver ,primer intento usando el ejemplo de la libreria :
Code: [Select]
#include <SPI.h>
#include "mcp_can_Err.h"
const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN);                                    // Set CS pin
unsigned long oldId[] = {344443334,544333212,887669876,333322555};
unsigned long newId[] = {211004335,111134553,232444322,776589000};
#define NUM_ID 4
// Lo hago de 4 elementos para el ejemplo,si funciona añades restantes y con las id correctas en numero (no hexadecimal por si acaso)

int getIdPosition(unsigned long Id){
  for( int cont = 0; cont < NUM_ID; cont ++){
    if(oldId[cont] == Id){
      return cont;
    }
  }
  return -1;
}

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

    if(CAN_MSGAVAIL == CAN.checkReceive()) {          // check if data coming   
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
        unsigned long oldId = CAN.getCanId();
        int idToFind = getIdPosition(oldId);
        if(idToFind != -1){
          CAN.sendMsgBuf(newId[idToFind], 1, len, buf); // Por cierto revisa aqui,en ejemplos veo (newId[idToFind], 0, len, buf)
        }
//        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();
    }
}


Hago dos arrays uno de las id que te da la maquina(oldId) y otro con las que los substituyen(newId),tienen que ir en el mismo orden y tendras que rellenarlos con valores verdaderos ,mejor con valores decimales (no hexadecimal).
Si hay datos a leer ,se leen y se supone se guardan en buf y el numero de caracteres en len.Se recoge el id de la trama y se busca en array oldId.Si se encuentra ,buscamos en array newId con el mismo indice para obtener id que le toca y se envia el mensaje con esa otra id.

JoseGD

Muchas Gracias _jose_

Esta tarde lo pruebo y te voy comentando

Gracias

JoseGD

Buenas _jose_, antes de nada te agradezco muchísimo tu ayuda.

He estado estudiando lo que me has mandado y mas o menos lo entiendo, ojala llegue algún dia a tener esa destreza programando.

Te comento esto:
En el ejemplo pone 0 por que usa ID no extendidas de 11bits (0x00) si pones un 1 son ID extendidas de 29 bits(0x0000000)
Code: [Select]

CAN.sendMsgBuf(newId[idToFind], 1, len, buf); // Por cierto revisa aqui,en ejemplos veo (newId[idToFind], 0, len, buf)


EL codigo funciona perfectamente,lo hice asin:
Code: [Select]

unsigned long oldId[] =   {0x15EFE411,0x15EFE412,0x15EFE413,0x15EFE414};
unsigned long newId[] = {0x01800001,0x01800002,0x01800003,0x01800004};


Pero al estar probando, me surge un gran problema, este código funciona perfectamente en las cuatro primeras paginas de la pantalla nueva.

Pero es las dos ultimas, que se usan para que la maquina ordene las piezas que ha cortado y monitorear todo, tengo que asignar a mi antojo la oldId a la newId, me explico, ahora mismo tal cual lo me los echo arriba estamos cambiando la ID 0x15EFE411 por la 0x01800001 y funciona perfectamente.

Pero ahora tengo estas cuatro ID:

Code: [Select]

0x01800101
0x01800102
0x01800103
0x01800103


y tengo que asignarlas  a las 20 oldID a mi antojo (bueno mas bien al antojo de la pantalla)

Se me ocurre hacer de momento usando el puerto serie ( ya le pondré algún teclado o alguna TFT para dejarlo acabado)

Si envió un dato '1' la ID 0x15EFE411 la mando por la 0x01800101, si es '2' la mando por la 0x01800102 y así con todas.....O sea tendría estas ultimas 4 ID que combinar con las 20 oldID.

Esto ya me parece mas complicado que se pueda hacer la verdad.

No se como agradecerte el tiempo empleado en ayudarme.

Gracias

_jose_

#36
May 14, 2020, 10:17 pm Last Edit: May 14, 2020, 10:18 pm by _jose_
Pero cuales son los criterios para mandar cualquiera de las 20 tramas a cualquiera de esas 4 id?Lo decides tu segun tus necesidades o se puede automatizar el envio de alguna manera? Ahora mismo esas tramas no se guardan,simplemente se reenvian con la id cambiadas tal cual van llegando.

JoseGD

No se puede automatizar, la tengo que elegir, te explico.

La pantalla original lo hacia todo ella automatico, entonces cuando la maquina llega al ultimo proceso en esta pantalla nueva,tenemos que seleccionar la ID que queremos para ver los parámetros, pero solo me permite esas 4 ID.

Yo con este aparato ( que lo compre y después me di cuenta que con arduino se hacia igual) he averiguado lo siguiente:

https://es.rs-online.com/web/p/kits-de-desarrollo-de-interfaz/7154255/

La trama1, los dos primeros bytes son para la presión que ejercen unos pistones, y asi me pegue muchas horas para averiguar que era cada byte de cada trama, que te quiero decir con esto, lo siguiente:

La trama1 nos indica la presión de los pintones
Las tramas 2,3,4 ,5 las temperaturas de diferentes sensores
Y asi con todas.
Hay tres tramas que lo único que hacen es camiar de pagina en la pantalla,segun el proceso de la maquina.

Entonces en las dos ultimas tenemos que decirle a esta pantalla: quiere ver la presión de los sensores y tenemos que mandar la trama oldid 1 con la newId 8, quiero ver las temperatura en este ultimo proceso, tenemos que mandar la oldId 3 por la newid 9 por ejemplo.

Ya que esta pantalla en el ultimo proceso no nos permite ver todo a la vez,solo nos deja ver cuatro campos, que serian cuatro ID, entonces tenemos que seleccionar lo que queremos ver.

Espero que lo hayas entendido.

Gracias

_jose_

Se puede aprovechar la ñapa de los arrays para añadir un tercer array de desvios en el que se pueden guardar las 4 id alternativas ,cuando oldId coincide con newId ,se busca tambien con ese mismo indice en el array de desvios y si hay una id guardada esa trama se envia tambien a esa id alternativa,lo que pasa es que esto implica tambien recoger comandos del serial,introducir/modificar/borrar en ese array las 4 id a desviar ,verificar que no haya mas de 4 id en el array,etc.la cosa se va complicando.

JoseGD

Pues si que se complica _jose_con lo contento que estaba cuando lo probé y funcionaba todo.
Voy a estudiar un poco, haber so soy capaz de hacer lo que me dices.

Me puedes por favor explicar esto
Code: [Select]

int getIdPosition(unsigned long Id){
  for( int cont = 0; cont < NUM_ID; cont ++){
    if(oldId[cont] == Id){
      return cont;
    }
  }
  return -1;
}



Haber si entendiendo esto puedo yo hacer otro array y hacer lo que me comentas.

Gracias

_jose_

Es una funcion a la que se le pasa como parametro Id que es del tipo unsigned long y devuelve un int ,que es la posicion del array donde se encontro que oldId y newId coinciden.Lo que hace es recorrer el array oldId y compara el contenido de cada posicion con el id que le pasamos,si es igual devuelve el valor de la variable cont en ese momento,que es del tipo int (recuerda que la funcion devuelve un int)
Si no encuentra ninguna coincidencia retorna -1,entonces antes de usar el indice se verifica con un if que el valor es diferente de -1 lo que quiere decir que hay una coincidencia.Luego se accede al array newId con el indice que nos devolvio la funcion para obtener el newId.

_jose_

Sobre el ejemplo anterior ,se añade un array desviosId ,en una funcion llamada en el setup() se rellena con 0 y en la tercera posicion ponemos manualmente una de las 4 id en la posicion 3.Cuando se encuentre una coincidencia en oldId ,se buscara tambien en el array desviosId y si hay un valor que no sea 0 ,se enviara tambien la trama a esa id,eso ocurrira cuando se reciba la id 0x15EFE413 que es la que esta en la tercera posicion de oldId i el contenido de esa trama se enviara tambien a 0x01800101
Code: [Select]
#include <SPI.h>
#include "mcp_can_Err.h"
const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN);
#define NUM_ID 4
unsigned long oldId[] =   {0x15EFE411,0x15EFE412,0x15EFE413,0x15EFE414};
unsigned long newId[] = {0x01800001,0x01800002,0x01800003,0x01800004};
unsigned long desviosId[NUM_ID]; // De momento 4 elementos ,luego seran los 20

void setArrayValues(){ // Se rellena el array con 0
  for(byte cont = 0; cont < NUM_ID ; cont ++){
    desviosId[cont] = 0; 
  }
  desviosId[2] = 0x01800101; // Ahora añadimos la primera de las cuatro id de la pantalla nueva al tercer elemento del array,entonces cuando se reciba
  //la oldId 0x15EFE413 que es el tercer elemento tambien,se enviara su trama a la id 0x01800101.Esto es fijo,luego se puede hacer por serial.
}

int getIdPosition(unsigned long Id){
  for( int cont = 0; cont < NUM_ID; cont ++){
    if(oldId[cont] == Id){
      return cont;
    }
  }
  return -1;
}

void setup(){
  Serial.begin(115200);
  setArrayValues();
  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(){
    unsigned char len = 0;
    unsigned char buf[8];

    if(CAN_MSGAVAIL == CAN.checkReceive()) {          // check if data coming   
        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
        unsigned long oldId = CAN.getCanId();
        int idToFind = getIdPosition(oldId);
        if(idToFind != -1){
          CAN.sendMsgBuf(newId[idToFind], 1, len, buf); // Por cierto revisa aqui ,en ejemplos veo (newId[idToFind, 0, len, buf)
          if(desviosId[idToFind] != 0){ // Si en el array desviosId hay un valor diferente de 0 es que hay una id nueva guardada y se envia la trama tambien.
            CAN.sendMsgBuf(desviosId[idToFind], 1, len, buf);
          }
        }
//        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();
    }
}

JoseGD

Buenas tardes _jose_ he probado esta mañana el código y la verdad que me quito el sombrero, funciona perfectamente.

He echo esto y lo he introducido en el void loop, por que lo puse ne le void setArrayValues, pero no funcionaba
Code: [Select]

  if (Serial.available())
  {
    dato = Serial.read();
  }
  switch (dato) {
    case '1':
      desviosId[2] = 0x01800101;

      break;
    case '2':
      desviosId[3] = 0x01800102;
      break;
  }


Es correcto colocarlo en el Loop o lo estoy haciendo mal?

Gracias

_jose_

#43
May 16, 2020, 09:46 pm Last Edit: May 16, 2020, 09:47 pm by _jose_
Si ,debe ir en el loop para que en cualquier momento puedas introducir caracteres
 por serial.Mejor asi todo dentro delbloque if:
Code: [Select]

if (Serial.available())
  {
    dato = Serial.read();
    switch (dato) {
      case '1':
        desviosId[2] = 0x01800101;

      break;
      case '2':
        desviosId[3] = 0x01800102;
      break;
    }
 }

La idea es que desviosId contenga 20 elementos y un maximo de 4 id guardadas,entonces habra que controlar el numero porque si ya hay 4 guardadas lo logico es que borres una de las que ya no quieres mostrar para guardar otra(poniendo un 0 en su contenido).

JoseGD

Quote
La idea es que desviosId contenga 20 elementos y un maximo de 4 id guardadas,entonces habra que controlar el numero porque si ya hay 4 guardadas lo logico es que borres una de las que ya no quieres mostrar para guardar otra(poniendo un 0 en su contenido).
Es verdad no había pensado como borralo, para que desviosId contenga 20 elementos, solo tengo que hacer esto,no.
Code: [Select]

#define NUM_ID 20


Y para parar en envió de algunas de las 4 id hago esto, no
Code: [Select]

desviosId[2] = 0;

Go Up