Saludos a todos.
Primero daros las gracias por todos vuestros aportes, que ma han ayudado mucho.
Pero, tengo un problema con el CANBus, no recoge datos en modo LISTEN.
Los datos en modo NORMAL los recoge sin problemas, pero en este modo, se me paran las comunicaciones de un sistema de seguridad.
Lo que estoy intentando, es captura datos del bus y guardarlos en una SD, con un sheld SPANKFUN. (como prueba para un proyecto).
Uso la libreria MCP2515 de David Harding, que funciona muy bien y es totalmente configurable, me he puesto en contacto con él, pero no ma ha contestado.
Os pongo una parte del código:
Can.ino
#include <SPI.h> // Libreria SPI de Arduino
#include <MCP2515.h> //Libreria para el controlador de CANBus MCP2515
#include <Time.h> //Libreria captura hora RTC
#include <Wire.h> //Libreria I2C
#include <DS1307RTC.h> // Libreria básica DS1307 que retorna el tiempo como: time_t
// Pin específicos de cómo el MCP2515, está cableado: CS_PIN activación línea SPI al controlador MCP2515
// INT_PIN lectura del pin de interrupción del MCP2515
#define CS_PIN 10 //Pin 10 Arduino
#define INT_PIN 2 //Pin 2 Arduino
// Se crea el objeto CAN, con los pines definidos en esas variables.
MCP2515 CAN(CS_PIN, INT_PIN);
//Declaramos los led de estado
//Led D7, pin Arduino 7, como mensaje recibido y estado interrupciones
int D7 = 7;
//Led D8, pin Arduino 8, como led auxiliar para fallo y estado interrupciones
int D8 = 8;
//Declaramos variable de iteración de secuencia inicio
// Ponemos a cero la variable de iteración "i"
byte i = 0;
void setup() {
// Poner código de configuración aquí, se ejecutar una vez:
//D7 y D8 como salida
pinMode(D7, OUTPUT);
pinMode(D8, OUTPUT);
//Velocidad de comunicación serie
Serial.begin(115200);
setSyncProvider(RTC.get); // Función que toma el tiempo del RTC
Serial.println("Empezamos ...");
Serial.println();
Serial.println();
digitalClockDisplay();
Serial.println();
Serial.println();
Serial.println();
// Configuración de las comunicaciones SPI
// setDataMode solo puede ser, SPI_MODE0 o SPI_MODE3 para el MCP2515
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
SPI.begin();
// Inicializar controlador CAN MCP2515 a la velocidad especificada y frecuencia de reloj de la Tj. CAN
// En el S9000, 250 kbps y a 16 MHz el oscilador de la Tj. CANBus. Podemos utilizar SJW como divisor sincronismo mensajes (250, 16, "1 al 4");
int baudRate=CAN.Init(250,16,1);
/*
Podemos elegir entre estos modos (estan definidos en MCP2515_defs.h):
MODE_CONFIG
MODE_LISTEN
MODE_LOOPBACK
MODE_SLEEP
MODE_NORMAL
*/
CAN.Mode(MODE_LISTEN);
if(baudRate>0) {
Serial.println("MCP2515 Inicializacion OK ... :-) ");
Serial.println("");
Serial.print("Velocidad de transmision (kbps): ");
Serial.println(baudRate,DEC);
// Secuencia led D7, D8 de inicio
for(i=0;i<4;i++) {
digitalWrite(D7, HIGH);
delay(50);
digitalWrite(D8, HIGH);
delay(50);
digitalWrite(D7, LOW);
delay(50);
digitalWrite(D8, LOW);
delay(50);
}
}
else {
Serial.println("MCP2515 Inicializacion KO... OH, OH... :-(( ");
}
Serial.println("");
Serial.println("PREPARADO ...");
Serial.println("");
}
// Telegrama CAN (en realidad, sólo las partes de expuestas por los MCP2515 RX / TX buffers)
// Nos llega el mensaje de la biblioteca, MCP2515.CPP
Frame message;
void loop() {
// poner código principal aquí, para ejecutar repetidamente:
message.id=0x00; //Ponemos a "0", la ID, para leer solo con ID mayores de "0".
// Esta aplicación utiliza el pin de interrupción "INT", 12, del MCP2515 12, para marcar los mensajes recibidos, en este caso los buffers RXB0 y RXB1.
if(CAN.Interrupt()) {
// Determina lo ocurrido al activarse la interrupción
byte interruptFlags = CAN.Read(CANINTF);
if(interruptFlags & RX0IF) {
// lee el buffer RXB0
message = CAN.ReadBuffer(RXB0);
digitalWrite(D7, HIGH);
delay(50);
}
if(interruptFlags & RX1IF) {
// lee el buffer RXB1
message = CAN.ReadBuffer(RXB1);
digitalWrite(D7, HIGH);
delay(50);
// (Este código, al recibir un mensaje por el segundo buffer, sobreescribe el primero)
}}
// Apagamos D7 recepción mensaje
digitalWrite(D7, LOW);
delay(50);
if(message.id>0x00) { //Leemos solo los ID, mayores de "0".
//if(message.id == 0x10 | message.id == 0x56){ // Seleccionamos los telegramas que queremos
// IMPRIME MENSAJE
//Serial.print("Time: ");
// digitalClockDisplay(); // Llamamos a la función y ponemos la hora de la muestra tomada.
Serial.print("ID: ");
Serial.print(message.id,HEX);
Serial.print(" EXT: ");
if(message.ide) {
Serial.print(" 1");
}
else {
Serial.print(" 0");
}
Serial.print(" DLC: ");
Serial.print(message.dlc,DEC);
Serial.print(" ");
// Imprime el número de datos que nos dice el DLC de telegrama CAN
Serial.print(" Datos: ");
for(i=0;i<message.dlc;i++) {
Serial.print(message.data[i],HEX);
Serial.print(" ");
}
Serial.println();
}
// Envía un mensaje de respuesta por cada uno de los datos recibidos
// Simplemente incrementar la identificación del mensaje y los bytes de datos, para mostrar la correcta transmisión
// Lo dejamos desconectado para no interferir en la comunicaciones del CANBus del S9000
//message.id++;
//for(i=0;i<message.dlc;i++) {
// message.data[i]++;
//}
//CAN.LoadBuffer(TXB0, message);
//CAN.SendBuffer(TXB0);
//} // Condición del IF de selección de telegramas
}
void digitalClockDisplay(){
// Imprimimos el tiempo con forma: hh:mm:ss dia-mes-año
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print("/");
Serial.print(month());
Serial.print("/");
Serial.print(year());
Serial.print(" ");
}
void printDigits(int digits){
// función de utilidad para la visualización del reloj digital: imprime : entre hora:minuto:segundo y pone un 0 si valor menor de 10
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
Dejo las librerías aquí;
Necesito de vuestra ayuda, no entiendo qué es lo que falla. No mando ningún dato y creo que las interrupciones se pueden utilizar en el modo LISTEN.
Gracias de antemano.
Probado con USB - CANBus de PEAK. Mando datos y OK en modo Normal con 29bits y 11bits.
En listen aparece BUSHEAVY.