Autor Tema: Mis experiencias con el BUS CAN  (Leído 680483 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: Mis experiencias con el BUS CAN
« Respuesta #810 en: 22 de Julio de 2010, 12:39:03 »
Hola!!! :-/

Solucione los problemillas de mis entrenadoras. Me había "cargado" el bootloader; lo programe de nuevo por el ICSP con mi Winpic800 y listo. Probe el ejmplo de Microingenia y va bien.

Seguiré con el ejemplo de comunicación CAN entre dos nodos; que me había planteado.

Cuando salga algo, o no salga daré noticias.

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7863
Re: Mis experiencias con el BUS CAN
« Respuesta #811 en: 22 de Julio de 2010, 14:20:07 »
Deberas prestar atencion al tema de los ID de los esclavos, ya que me parece que por alli hay un problema.
En la conexion 1 a 1 (1 Maestro y 1 esclavo) anda bien, porque el maestro es cero y el no va a contestar su propio requerimiento, pero cuando haya mas de un esclavo en el bus, ahi ya no podria funcionar de ningun modo.
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado kR105

  • PIC10
  • *
  • Mensajes: 1
Re: Mis experiencias con el BUS CAN
« Respuesta #812 en: 23 de Julio de 2010, 00:48:33 »
Estimados, odio cuando mi primer post en un foro es pidiendo ayuda jaja pero este tema me tiene intrigadisimo y necesito un empujoncito  :)

Tengo un PIC 18F4685 y quiero comunicarlo con el puerto CAN/OBDii de mi auto, he visto que se puede hacer, pero lo que quiero no es pasarle los datos al PC sino que manejarlos directamente en el pic (dependiendo de los datos leidos, manejar un relay, leds, lcd, etc). ¿Es posible hacer eso solo usando el pic? (Estoy tratando de no usar la elm327). ¿Puedo hacer eso con pics mas pequeños o necesito uno con ecan?

Muchas gracias y disculpen por desviar el tema, pero como aca hablan de esto, consideré que es el mejor lugar :)

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: Mis experiencias con el BUS CAN
« Respuesta #813 en: 23 de Julio de 2010, 11:53:16 »
Hola kR105; yo también soy principiante en la comunicaión CAN y te aseguro que en este foro aclararás muchas dudas (da un vistazo al post, es extenso hasta llegar a las líneas que ahora escribo).

Por lo que he leído aquí, si el PIC no dispone de CAN integrado has de utilizar un controlador (p.e:MCP2515) y un trasnceptor (p.e:MCP2551). En caso contrario has de utilizar al menos el trasceptor. No olvides colocar en paralelo una resistencia de 120ohmios en los extremos de la línea.

Att,
Un saludo.

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: Mis experiencias con el BUS CAN
« Respuesta #814 en: 26 de Julio de 2010, 15:39:44 »
Hola amigos; después de poner todo en marcha; me costo por la poca experiencia he conseguido que funcione el siguiente ejemplo:

<COMUNICACION CAN 2 NODOS>

NODO A->ID=0 MAESTRO
NODO B->ID=1 ESCLAVO

Cuando se pulse una tecla en NODO A (b2) se envia un byte(0xFF) al NODO B lo que hace encender durante 4 segundos los leds asociados al puerto D (nodo B).

El NODO B envía un acuse de recibo al NODO A encenciendo un led asociado a un puerto de dicho nodo.


El código para CCS:

Código: [Seleccionar]
//CANMASTER.C


#include "config18F4550Trainer.c"
#include "usb/usb_cdc.h"
#include "usb/usb_bootloader.h"
#include "can/can-mcp251x.c"

#define BUTTON PIN_B2
#define BUTTON_PRESSED !input(BUTTON)

// Variables send can bus
struct rx_stat rxstat;
int32 rx_id;
int8 rx_len;

// Variables reception can bus
int32 tx_id;
int1 tx_rtr=0;
int1 tx_ext=1;
int8 tx_len=7;
int8 tx_pri=3;
int32 id=0;//del maestro
int32 rx_id_esclavo=1;
int8 datos=0;
int8 datos_slave=0;




void main()
{
   tx_id=id;
   
   disable_interrupts(GLOBAL);
   disable_interrupts(INT_TIMER0);
   
   setup_timer_0(RTCC_DIV_2);
   
   enable_interrupts(GLOBAL);
   datos=0xFF;
   ON(LEDV);
   OFF(LEDR);
   delay_ms(800);
   ON(LedR);
   OFF(LedV);
   delay_ms(800);
   ON(LedV);
   OFF(LedR);
   can_init();    // Init can bus
 
     
   while(TRUE)
   {
     
      if(can_kbhit())
      {
         can_getd(rx_id, &datos_slave, rx_len, rxstat); // read data can bus
         
         if(rx_id_esclavo==rx_id)
         {
         disable_interrupts(INT_TIMER0);
         ON (LedR);
         ON (LedV);//verde&rojo=amarillo
         delay_ms(2000);
         OFF (LedR);
         OFF (LedV);
         
         }
      } 
     
     
      if(BUTTON_PRESSED)
      {
      while(BUTTON_PRESSED){}
      delay_ms(200);
   
      can_putd(tx_id,&datos,tx_len,tx_pri,tx_ext,tx_rtr);//send a byte=0xFF
      }
     
   }//while
}//main
     
     
   

#int_Timer0    // if after 10ms from the sending no data is received, indicate the failure of communications lighting the red LED
void timer0(void)
{
   disable_interrupts(INT_TIMER0);
   ON(LedR);
}

Código: [Seleccionar]
//CANSLAVE


#include "config18F4550Trainer.c"
#include "usb/usb_cdc.h"
#include "usb/usb_bootloader.h"
#include "can/can-mcp251x.c"
//#use fast_io(D)




// Variables send can bus
struct rx_stat rxstat;
int32 rx_id;
int8 rx_len;

// Variables reception can bus
int32 tx_id;
int1 tx_rtr=0;
int1 tx_ext=1;
int8 tx_len=7;
int8 tx_pri=3;
int32 rx_id_maestro=0;
int32 id = 1;//del esclavo
int8 datos = 0;
int8 datos_slave=0;

void main()
{
 
   tx_id=id;
   datos_slave=0x01;
   can_init(); // Init can bus
   
   ON(LedV);
   OFF(LedR);
   
   while(TRUE)
   {
      if ( can_kbhit() ) // check for data on the can bus
      {
         can_getd(rx_id, &datos, rx_len, rxstat); // read data can bus
         
         if (rx_id_maestro == rx_id)
         {
           OFF(LedV);
           ON (LedR);
       
           ON (pin_D0);
           ON (pin_D1);
           ON (pin_D2);
           ON (pin_D3);
           ON (pin_D4);
           ON (pin_D5);
           ON (pin_D6);
           ON (pin_D7);
           
           delay_ms(4000);
           OFF (LedR);
       
           OFF (pin_D0);
           OFF (pin_D1);
           OFF (pin_D2);
           OFF(pin_D3);
           OFF (pin_D4);
           OFF (pin_D5);
           OFF (pin_D6);
           OFF (pin_D7);
           
         }
         can_putd(tx_id, &datos_slave, tx_len,tx_pri,tx_ext,tx_rtr); //acuse de recibo
      }
   }
}
    Echazle un vistazo por si veis algo que esté mal o simplemente pueda mejorarse. :lol: :-/ ;-)



Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7863
Re: Mis experiencias con el BUS CAN
« Respuesta #815 en: 26 de Julio de 2010, 15:57:19 »
No esta mal, deberia funcionar OK.
El unico detalle es que transmites y recibes 7 Bytes, no uno.
Como en la funcion de recepcion recibes los mismos bytes no te dara error, pero debes practicar enviando y recibiendo con diferentes cantidad de bytes (entre 1 y 8) para ver como se comporta la cosa.

No importa si los datos son diferentes, en un solo mensaje puedes enviar y recibir hasta 8 Bytes de diferente origen o 4 words o 2 doble words, y rearmar en la interpretacion de tu respuesta nuevamente los datos.
Hasta una flotante podrias enviar.. :mrgreen:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: Mis experiencias con el BUS CAN
« Respuesta #816 en: 27 de Julio de 2010, 08:19:28 »
Bien, así lo haré... prácticaré a enviar mensajes con mayor o menor cantidad de bytes.

Me surge una duda y no encontré la información necesaria en el datasheet.

Trabajando con el primitivo 16f84 si pongo la directiva #byte PORTB=0X06

puedo luego manejar todo el puerto de un plumazo y en este caso me interesaria mucho, ya que en el momento de recibir el byte puedo volcarlo directamente sobre el puerto, sin ir uno a uno:

PORTD=*datos;

Gracias, saludos

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7863
Re: Mis experiencias con el BUS CAN
« Respuesta #817 en: 27 de Julio de 2010, 08:33:05 »
Recuerda que la variable datos alli esta manejada por un puntero, que lee hasta la posicion que tu le mandas leer, en este caso 7.

La mejor forma es manejarse con el byte especifico que quieres mostrar, ya que si manejas el puntero vas a mostrar el ultimo byte leido y eso cambiara segun la cantidad usada.

lo mejor sera usar esta forma de mostrarlo:
Código: C
  1. PortB=datos[0] // en caso de usar el primer byte
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: Mis experiencias con el BUS CAN
« Respuesta #818 en: 27 de Julio de 2010, 15:48:26 »
Hola, he probado lo que me dices, pero el compilador me dice que "datos debe ser definida como puntero"; yo defino datos como int8; como un byte en memoria.

El único modo de cargar lo que llega al esclavo a través del bus es con:

Código: [Seleccionar]
output_D(datos);

Por otro lado aunque compila, no hace efecto en todo lo referente a manejar el puerto D con la siguente instrucción:

Código: [Seleccionar]
PORTD=0XFF; // un ejemplo
PORTD=datos;//otro ejemplo que con output_D() si tiene efecto

Al principio ya no compilaba Y daba error en "PORTD" como no definido.

Al principio del programa añadí:

Código: [Seleccionar]
#use standard_io(D)
#byte PORTD = 0x00
no se si es correcto;

Gracias; toda ayuda se agradece para manejar eficientemente lo que llega por el bus.

Att,
 :-/ :-/ :-/

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7863
Re: Mis experiencias con el BUS CAN
« Respuesta #819 en: 27 de Julio de 2010, 15:54:54 »
 :D :D :D :D :D :D :D

El 16f84 no tiene portD, no interesa si lo defines o no !!! :mrgreen: :mrgreen:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado daltonico82

  • PIC12
  • **
  • Mensajes: 89
Re: Mis experiencias con el BUS CAN
« Respuesta #820 en: 28 de Julio de 2010, 03:58:49 »
Hola; en efecto, sé que el 16f84 no tiene puerto D. Tiene 6 pines de A y el puerto B completo.

Mi pregunta es como defino el pueto D para el 18f4550 para manejarlo entero.

Y más concretamente me refiero a que:

Código: [Seleccionar]
PORTD=datos[0], no va.


Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7863
Re: Mis experiencias con el BUS CAN
« Respuesta #821 en: 28 de Julio de 2010, 08:15:00 »
Ahhh!!
Bien , entendi mal, crei que te referias al 16f84...

Los puertos de la linea PIC18 estan en otras direcciones.

Una forma que permite configuracion automatica seria usando getenv()

Quedaria mas o menos asi:
Código: C
  1. #byte PORTD =  getenv("SFR:PORTD")     //portd

Citar
SFR:name
 Returns the address of the specified special file register. The output format can be used with the preprocessor command #bit. name must match SFR denomination of your target PIC (example: STATUS, INTCON, TXREG, RCREG, etc)
 

La otra es ir a la hoja de datos y leer cual es la direccion donde esta PortD.
La primera es mejor porque si el puerto existe automaticamente devuelve la direccion del mismo. (no hay que trabajar tanto) :mrgreen: :mrgreen: :mrgreen:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado sergio_silva

  • PIC10
  • *
  • Mensajes: 6
Re: Mis experiencias con el BUS CAN
« Respuesta #822 en: 19 de Agosto de 2010, 20:26:37 »
Hola, tengo una pregunta:

en la funcion: can_getd(): ----> int1 can_getd(int32 & id, int * data, int & len, struct rx_stat & stat)

Returns:
//      id - ID who sent message
//      data - pointer to array of data
//      len - length of received data
//      stat - structure holding some information (such as which buffer
//             recieved it, ext or standard, etc)
//
//    Returns:
//      Function call returns a TRUE if there was data in a RX buffer, FALSE
//      if there was none.

si el id contiene el ID del PIC que enviou el mensaje, entonces está mal hacer:

if(can_kbhit())
      {
         can_getd(rx_id, &datos_slave, rx_len, rxstat); // read data can bus
         
         if(rx_id == id_PIC)
         {

porque id_PIC es el id del PIC que recebe el mensaje, no del PIC que envia, pero en mi codigo funciona bien assim  :huh: :huh: :huh:.

Saludos.

Desconectado MGLSOFT

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 7863
Re: Mis experiencias con el BUS CAN
« Respuesta #823 en: 19 de Agosto de 2010, 22:12:37 »
Hola Sergio.
Si funciona es porque el PIC que envia el mensaje esta solo en el bus, junto al master que lo recibe.
Como la comparacion la pasa bien, es normal que lo reciba...

Mira lo que hace el codigo:
  • En el If pregunta si hubo un dato en el buffer de recepcion.
  • Si hubo dato, lee el mensaje con la funcion Can_Getd()
  • Luego toma el ID que viene en ese mensaje y lo compara con el contenido de una variable que tiene el ID que se espera recibir...
  • Si es igual al esperado, continua con otras acciones.....

Eso da bien en la comparacion del tercer punto, por lo tanto no constata otra cosa...

Preguntame si eso esta bien, te dire que no, ya que no debe haber dos ID iguales en el BUS, porque contestarian ambos a la vez, sin funcionar el arbitraje, que precisamente lo que hace es discriminar entre dos ID muy parecidos para saber cual puede responder, por lo tanto es un error grave tener dos ID iguales!!!

Como se hace en la practica??
Es mas facil que esto ni siquiera llegue al PIC, o sea que la decision de cual ID se recibe o no, se hace a traves de los filtros (mascaras logicas) aplicadas a los bufferes de recepcion.

O sea que en un PIC determinado ni siquiera necesito saber si el mensaje es de un ID determinado, ya que puedo filtrarlo sin que ese mensaje llegue siquiera a un buffer de recepcion.

Se entiende?? :lol: :lol:
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado sergio_silva

  • PIC10
  • *
  • Mensajes: 6
Re: Mis experiencias con el BUS CAN
« Respuesta #824 en: 20 de Agosto de 2010, 07:51:02 »
Hola MGLSOFT, gracias por la explicación.

Quanto a los filtros, sei que há una funcion para isso, a can_set_id();

Si yo quiero que el ID de PIC seja 200, para activar los filtros está correcto hacer:
( yo uso el modo extendido)


#define ID 200;

void main()
{

 can_init();       
   
 can_set_mode(CAN_OP_CONFIG);

 can_set_id(RX0MASK, 0x1FFFFFFF, 1);  //set mask 0
 can_set_id(RX0FILTER0, ID, 1);  //set filter 0 of mask 0
 can_set_id(RX0FILTER1, ID, 1);  //set filter 1 of mask 0

 can_set_id(RX1MASK, 0x1FFFFFFF, 1);  //set mask 1
 can_set_id(RX1FILTER2, ID, 1);  //set filter 0 of mask 1
 can_set_id(RX1FILTER3, ID, 1);  //set filter 1 of mask 1
 can_set_id(RX1FILTER4, ID, 1);  //set filter 2 of mask 1
 can_set_id(RX1FILTER5, ID, 1);  //set filter 3 of mask 1

 can_set_mode(CAN_OP_NORMAL);

(...)

Saludos



 

anything