CANBUS - am I trying to do too much or just doing it badly?

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

  while(1){
    
    if (CAN_available()) {  //is a message recieved
    
      digitalWrite(led,ledState);
      ledState = !ledState;
 
      currentTime = millis(); 
      CAN_getMessage (); //subroutine for extracting message from buffer
      CAN_processMsg ();

      if(currentTime >= (cDisplayTime + DisplayDelay)){ 
        Update_Values();
        cDisplayTime = currentTime; // Updates cloopTime
      } //end if
      
    }//end void Update_Parameters
  }//end while
}//end void CAN_Capture
//-----------------------------------------------------------------------------------------------







void CAN_processMsg(){
//----------------------------------------------------------------------------------------------------------------

Arbid_Updates[0]++;   //log the number of passes through this loop

unsigned int Buffer;
    //populate the CAN_P array with extracted parameters
    switch (id) {
    //----------------------------------------------------------------------------------------------------------------
      case 0x80:  //1
              CAN_P[0] = data[0];                                //aps1
              CAN_P[1] = data[1];                                //aps2    
              CAN_P[2] = data[7];                                 //apsCombined?
              
              Buffer=(data[5]<<8) + data[6];
                CAN_P[3] = int(Buffer/RPM_Rounding)*RPM_Rounding; //RPM 
              
              Arbid_Updates[1]++; 
         break;
    //----------------------------------------------------------------------------------------------------------------
      case 0x150:  //2
              CAN_P[4] = data[1];  				//Unknown1 
              CAN_P[5] = data[2];  				//Unknown2 
              CAN_P[6] = data[3];  				//Idle_Cont               
              CAN_P[7] = ((data[6]%2)<<8)+data[7];  		//Unknown3 
              
              Arbid_Updates[2]++; 
         break;   
    //----------------------------------------------------------------------------------------------------------------          
      case 0x100:  //3
              CAN_P[8] = data[3]-40;                           //Eng_Temp 
              CAN_P[9] = data[5]-40;                           //Amb_Temp 
	      CAN_P[10] = data[4];                              //Batt_v *
              CAN_P[11] = data[2];                              //Ignition
              
              Arbid_Updates[3]++; 
        break;  
    //----------------------------------------------------------------------------------------------------------------
      case 0x18: //4
              CAN_P[12] = ((data[4]>>4)-1)/2;                   //gearPOS 
              CAN_P[13] = (((data[4]%16)*256) + data[5])*0.15;  //Rspeed 
              Buffer = data[7]%16;                             // minus 8 will throw an error whilst the bike is initialising as values lower than 4 are produced      dtc 
              if (Buffer >=8) CAN_P[14] = Buffer-7;  
                else CAN_P[14] = 0;  
              CAN_P[15] =  data[1];                            //TPS1          
              CAN_P[16] =  data[6];                            //Fuel Level    
              
              Arbid_Updates[4]++; 
        break;          
    //----------------------------------------------------------------------------------------------------------------
      case 0x300:  //5
              CAN_P[17] = data[6]>>4;                           // Clock hours
              CAN_P[18] = data[6]%16;                           // Eng_Mode*
              
              CAN_P[19] = int(((data[4]<<8)+data[5])/kmsTomiles);// Mileage          
              CAN_P[20] = data[3]/2;                            // Clock Minutes
              
              Arbid_Updates[5]++;      
        break;            
    //----------------------------------------------------------------------------------------------------------------
      case 0x360:  //6
              CAN_P[31] = data[2];                           // RP_Fbk   Rear Pre load position feedback
              
              Arbid_Updates[6]++;               
        break;     
        
    //----------------------------------------------------------------------------------------------------------------
      case 0x20:   //7
              byte BufferLights = data[0]>>4;
              byte BufferBrake = (data[0]>>4)%2;
              CAN_P[21] = BufferBrake;                                 //brake 
              CAN_P[22] = BufferLights-BufferBrake;                          //Indicator

              Sus[1] = data[3];              // ARBID 20 B3     F_Rebound *   10
              Sus[0] = data[4]>>4;           // ARBID 20 B4(1)  F_Comp    *   9 
              Sus[3] = data[4]%16;           // ARBID 20 B4(2)  R_Rebound *   12      
              Sus[2] = data[5]>>4;           // ARBID 20 B5(1)  R_Comp    *   11
 
              for (int i=0; i<=3; i++) {
                if (Sus[i]!=Sus_Old[i]) UpdateSus = true;
              }
              if (UpdateSus == true) Update_Sus();  
           
              CAN_P[23] = data[5]>>4;               //R_Preload_cmd  

              CAN_P[24] = data[1];                  // Fspeed_1
              CAN_P[25] = data[2];                  // Fspeed_2
              CAN_P[26] = (data[1]<<8)+data[2];     // Fspeed_C
              
              Arbid_Updates[7]++; 
        break;  
    //----------------------------------------------------------------------------------------------------------------


    }//end switch
    //----------------------------------------------------------------------------------------------------------------  
}//end CAN_processMsg
//-----------------------------------------------------------------------------------------------


void Update_Sus(){
  
  byte FR1, FR2, FC1, FC2, RR1, RR2, RC1;
  
  for (int i=0; i<=3; i++) {
    Sus_Old[i]=Sus[i];
  }
  
  FR1 = ((Sus[1]-(Sus[1]%8))/8)+1;
  FR2 = (Sus[1]%8)*4;
  FC1 = ((Sus[0]-(Sus[0]%4))/4)+1;
  FC2 = (Sus[0]%4)*8;
  RR1 = ((Sus[3]-(Sus[3]%2))/2)+1;
  RR2 = (((Sus[3]%2)%2)*16)+1;
  RC1 = (Sus[2]%16);

  CAN_P[27] = FC1+FR2;      //FC
  CAN_P[28] = FR1;         //FR
  CAN_P[29] = RC1+RR2;     //RC
  CAN_P[30] = RR1+FC2;     //RR

  UpdateSus = false;
  
} //end Print_Suss




void Update_Values(){

  Serial.print("D,");  //Denote the start of the data stream 
  
  for (int i = 0; i <= paramQty-1; i++) { //loop through and print out entire CAN_P array delimited by commas
    Serial.print(CAN_P[i]);
    Serial.print(",");
  }
  
  Serial.print(int(currentTime/10^6)); 
  Serial.print(",");
  
  for (int i=1; i<=ArbidQty-1; i++) { //loop through and print out entire Arbid_Update array delimited by commas
    Serial.print(Arbid_Updates[i]);
    Serial.print(",");
  } 
  Serial.print(Arbid_Updates[0]);
  Serial.print(",");
  Serial.println();  //Denote the end of the data stream 
  
      digitalWrite(led2,led2State);   
      led2State = !led2State;  
      
}//end Update_Display 
//-----------------------------------------------------------------------------------------------

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.

Thanks for the hint ref attaching code.

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?