I've got problems with my automotive CANBUS sniffing project. Arduino Uno R3, Sparkfun CANBUS shield and bluetooth adapter. I'm trying to snif the CANBUS traffic on my motorbike and send selected bits of it over bluetooth to android. I'm a relative newbe to both Arduino and Android, but have something that is functioning. Problem is I seem to be missing quite a lot of the CANBUS traffic.
An earlier project using the same hardware but logging ALL the data (8 bytes per message) straight to SD card seemed to capture a substantial amount of data (it appeared to be all of it), so I assume the shield and arduino are able to keep up with the pure reading bit. The problem I now seem to have is that when I try and decode some of the info (e.g. turn bytes into things like RPM), store it in an array and then send updates to android (every 1/10th of a second I rad the array and print it to the bluetooth serial adapter) I miss a lot of data (some messages/ARBIDs only update every 5-10 seconds as opposed to several times a second).
I assume it is the SWITCH CASE that is slowing it down? Or is it likely to be taking time out to serial.print to bluetooth ? Any ideas?
code below, I apologies if it is a mess as I am a newbie
#include <SD.h> /* Library from Adafruit.com */
#include <SoftwareSerial.h>
#include <SPI.h>
#include "mcp2515.h"
#define DEFAULT_CAN_ID 0x0555
// added for filter and can changes
#define MASK_0 0x20
#define MASK_1 0x24
#define FILTER_0 0x00
#define FILTER_1 0x04
#define FILTER_2 0x08
#define FILTER_3 0x10
#define FILTER_4 0x14
#define FILTER_5 0x18
//Pin definitions
#define SCK_PIN 13 //Clock pin
#define MISO_PIN 12 //Mater in Slave output
#define MOSI_PIN 11 //Master out Slave input
#define SS_PIN 10 //SS pin
#define SD_PIN 9 //pin for SD card control
#define RESET_PIN 2
#define INT_PIN 3
//Joystick pin definitions
#define UP A1
#define RIGHT A2
#define DOWN A3
#define CLICK A4
#define LEFT A5
#define WRITE 0x02 //read and write comands for SPI
/* Operation Modes */
enum CAN_MODE {
CAN_MODE_NORMAL, /* Transmit and receive as normal */
CAN_MODE_SLEEP, /* Low power mode */
CAN_MODE_LOOPBACK, /* Test mode; anything "sent" appears in the receive buffer without external signaling */
CAN_MODE_LISTEN_ONLY, /* Receive only; do not transmit */
CAN_MODE_CONFIG, /* Default; Allows writing to config registers */
CAN_MODE_COUNT
};
unsigned long time; //used for time stamp
//CanMessage message;
int led = 8;
int led2 = 7;
byte i;
uint8_t message;
/** A flag indicating whether this is an extended CAN message */
uint8_t extended;
/** The ID of the CAN message. The ID is 29 bytes long if the
* extended flag is set, or 11 bytes long if not set. */
uint32_t id;
/** The number of bytes in the data field (0-8) */
uint8_t len;
/** Array containing the bytes of the CAN message. This array
* may be accessed directly to set or read the CAN message.
* This field can also be set by the setTypeData functions and
* read by the getTypeData functions. */
uint8_t data[8];
/* Define Joystick connection */
#define paramQty 32 //number of parameters to be read and sent to Android
int CAN_P[paramQty];
#define ArbidQty 8 //number of distinct ARBIDs to be read and sent to Android
unsigned long Arbid_Updates[ArbidQty+1];
boolean Changed[paramQty];
unsigned long currentTime;
unsigned long cDisplayTime;
unsigned long cJoystickTime;
unsigned long counter=0;
int DisplayDelay = 100;
int RPM_Rounding = 50;
float kmsTomiles = 1.609347088;
boolean ledState = LOW;
boolean led2State = LOW;
unsigned int Sus_Old[4] = {0,0,0,0};
unsigned int Sus[4] = {0,0,0,0};
boolean UpdateSus = false;
//************************ Setup ****************************
void setup()
{
digitalWrite(led,HIGH);
digitalWrite(led2,HIGH);
// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))
// set the slaveSelectPin as an output
pinMode (SCK_PIN,OUTPUT);
pinMode (MISO_PIN,INPUT);
pinMode (MOSI_PIN, OUTPUT);
pinMode (SS_PIN, OUTPUT);
pinMode(RESET_PIN,OUTPUT);
pinMode(INT_PIN,INPUT);
pinMode(led,OUTPUT); //setup LED
pinMode(led2,OUTPUT); //setup LED
digitalWrite(INT_PIN,HIGH);
//Set up Joystick Pins
pinMode(UP,INPUT);
pinMode(DOWN,INPUT);
pinMode(LEFT,INPUT);
pinMode(RIGHT,INPUT);
pinMode(CLICK,INPUT);
/* Enable internal pull-ups on JS pins */
digitalWrite(UP, HIGH);
digitalWrite(DOWN, HIGH);
digitalWrite(LEFT, HIGH);
digitalWrite(RIGHT, HIGH);
digitalWrite(CLICK, HIGH);
// initialize CAN bus
CAN_begin(MCP2515_SPEED_500000); // set can baud rate
CAN_setMode (CAN_MODE_LISTEN_ONLY); // set can mode
Serial.begin(9600); //set up serial port
delay(100);
//initialise the changed array
for (int i=0; i<=paramQty-1; i++) Changed[i] = true;
for (int i=0; i<=paramQty-1; i++) CAN_P[i]=0;
for (int i=0; i<=ArbidQty-1; i++) Arbid_Updates[i]=0;
digitalWrite(led,LOW);
digitalWrite(led2,LOW);
delay(500);
}
void loop()
{
if (!CAN_available()) {
Serial.println("Can bus not available. Check connections,");
digitalWrite(led,HIGH); //D8 light means waiting for Can to be connected
}
while(!CAN_available()) {
} //stop here and loop while waiting for Canbus to be connected
Serial.println("Can Bus Connected and available,");
currentTime = millis();
cDisplayTime = currentTime;
Serial.println("about to start CAN_Capture,");
CAN_Capture();
}//end loop
I haven't looked at the code. If your sketch is too big to be included inline then attach it as a file.
You mention that the problem starts when you sent the data via bluetooth. I suggest you look at the data rate on the CANBUS interface, work out the quantity of data you'll be sending over the BT serial connection and compare that to the speed of the serial connection. If the serial utilisation is greater than the CANBUS utilisation then a direct stream from one to the other would be problematic.
I'm not attempting to send all the CAN messages, just a snapshot of about 30-40 values (as a comma separated string e.g. 14,10,2300,157,1,2,.....etc) 10 times a second. I'm not sure how to calculate it, but I assume that 9600baud is sufficient for that?. The data seems to be getting transmitted as the millis counter value that I also send to the phone seems to be refreshing OK. The thing that doesn't seem to be happening anywhere near as frequently as I would expect is the reading of the CAN messages and the subsequent updating of the array that I am storaging the last known values that are the source of the 'snapshot'.
Each character is 8 bits, a comma is another 8 bits.. 40 double digit values separated by a comma is 120 characters,each 8 bits in length..that's 960 bits.. Trying to send that 10 times Ina second is 9600 bps, or baud.. That's maxing out your serial output with no room for overhead.. Try your code with just 5 values for now,see how it works.. Can you up your bluetooth baud rate? Honestly not sure if your too busy sending data to be reading the can bus?