SparkFun CAN-BUS Shield

Hello,

I am trying to use a CAN-BUS Shield and seem to be messing up,
I am trying to use some code off a website (http://www.cantanko.com) that is pretty much what i am trying to do.
Every time I try to use this code i get errors :

In function `loop':
36: undefined reference to `CAN'
36: undefined reference to `CAN'
In function `setup':
21: undefined reference to `CAN'
21: undefined reference to `CAN'

This is the code i am trying to use:

#include <SoftwareSerial.h>
#include <mcp_can.h>
#include <SPI.h>

#define CANint 2
#define LED2 8
#define LED3 7

void setup() {
  Serial.begin(115200);
  Serial.println("Init...");

  Serial.println("Setup pins");
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(CANint, INPUT);

  digitalWrite(LED2, LOW);

  Serial.println("CAN init:");
  if (CAN.begin(CAN_500KBPS) == CAN_OK) {
    Serial.println("OK!");
  } else {
    Serial.println("fail :-(");
    while (1) {
      Serial.print("Zzz... ");
      delay(1000);
    }
  }
}

unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char otmp[8] = {255,255,255,255,255,255,255,255};

void loop() {
  CAN.sendMsgBuf(0x00, 0, 8, otmp);
  delay(50);
}

Can any one help?

Thanks

Hi Waldo

As well as downloading the code of the sketch, have you downloaded the library mcp_can and put it in the Arduino IDE's libraries folder? Googling for mcp_can took me to this page.

All the best

Ray

Hello Ray,

Thanks for the reply, I have got the right library installed (well i think i have)

I don't really understand the error tho, I am pretty new to all this and am just jumping in lol.

would the "CAN" be defined in the mcp_can.h ?

Thanks

Possibly. You could open up mcp_can.h to see if it is declared there.

Also, did the library come with any example sketches? Even if they don't do what you want, you could check that you can compile them OK.

And sorry for asking, you probably know this anyway, but did you exit the Arduino IDE and run it again after installing the library?

Regards

Ray

Hello,

Please do ask all the stupid questions, as i am sure i am missing something simple. Altho i have restarted arduio after installation.

The example sketches do seem to work, however this is the library that was said will work with the sketch that i am trying to use.

I have had a look at the mcl_can.h file but to be honest i am not 100% sure how is would look if "CAN" was declared. see below:

/*
  mcp_can.h
  2012 Copyright (c) Seeed Technology Inc.  All right reserved.

  Author:Loovee
  Contributor: Cory J. Fowler
  2014-1-16
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-
  1301  USA
*/
#ifndef _MCP2515_H_
#define _MCP2515_H_


#include "mcp_can_dfs.h"
#define MAX_CHAR_IN_MESSAGE 8

class MCP_CAN
{
    private:
    
    INT8U   m_nExtFlg;                                                  /* identifier xxxID             */
                                                                        /* either extended (the 29 LSB) */
                                                                        /* or standard (the 11 LSB)     */
    INT32U  m_nID;                                                      /* can id                       */
    INT8U   m_nDlc;                                                     /* data length:                 */
    INT8U   m_nDta[MAX_CHAR_IN_MESSAGE];                            	/* data                         */
    INT8U   m_nRtr;                                                     /* rtr                          */
    INT8U   m_nfilhit;
    INT8U   SPICS;

/*
*  mcp2515 driver function 
*/
   // private:
   private:

    void mcp2515_reset(void);                                           /* reset mcp2515                */

    INT8U mcp2515_readRegister(const INT8U address);                    /* read mcp2515's register      */
    
    void mcp2515_readRegisterS(const INT8U address, 
	                       INT8U values[], 
                               const INT8U n);
    void mcp2515_setRegister(const INT8U address,                       /* set mcp2515's register       */
                             const INT8U value);

    void mcp2515_setRegisterS(const INT8U address,                      /* set mcp2515's registers      */
                              const INT8U values[],
                              const INT8U n);
    
    void mcp2515_initCANBuffers(void);
    
    void mcp2515_modifyRegister(const INT8U address,                    /* set bit of one register      */
                                const INT8U mask,
                                const INT8U data);

    INT8U mcp2515_readStatus(void);                                     /* read mcp2515's Status        */
    INT8U mcp2515_setCANCTRL_Mode(const INT8U newmode);                 /* set mode                     */
    INT8U mcp2515_configRate(const INT8U canSpeed);                     /* set boadrate                 */
    INT8U mcp2515_init(const INT8U canSpeed);                           /* mcp2515init                  */

    void mcp2515_write_id( const INT8U mcp_addr,                        /* write can id                 */
                               const INT8U ext,
                               const INT32U id );

    void mcp2515_read_id( const INT8U mcp_addr,                        /* read can id                  */
                                    INT8U* ext,
                                    INT32U* id );

    void mcp2515_write_canMsg( const INT8U buffer_sidh_addr );          /* write can msg                */
    void mcp2515_read_canMsg( const INT8U buffer_sidh_addr);            /* read can msg                 */
    void mcp2515_start_transmit(const INT8U mcp_addr);                  /* start transmit               */
    INT8U mcp2515_getNextFreeTXBuf(INT8U *txbuf_n);                     /* get Next free txbuf          */

/*
*  can operator function
*/    

    INT8U setMsg(INT32U id, INT8U ext, INT8U len, INT8U *pData);    /* set message                  */  
    INT8U clearMsg();                                               /* clear all message to zero    */
    INT8U readMsg();                                                /* read message                 */
    INT8U sendMsg();                                                /* send message                 */

public:
    MCP_CAN(INT8U _CS);
    INT8U begin(INT8U speedset);                              /* init can                     */
    INT8U init_Mask(INT8U num, INT8U ext, INT32U ulData);           /* init Masks                   */
    INT8U init_Filt(INT8U num, INT8U ext, INT32U ulData);           /* init filters                 */
    INT8U sendMsgBuf(INT32U id, INT8U ext, INT8U len, INT8U *buf);  /* send buf                     */
    INT8U readMsgBuf(INT8U *len, INT8U *buf);                       /* read buf                     */
    INT8U checkReceive(void);                                       /* if something received        */
    INT8U checkError(void);                                         /* if something error           */
    INT32U getCanId(void);                                          /* get can id when receive      */
};

extern MCP_CAN CAN;
#endif
/*********************************************************************************************************
  END FILE
*********************************************************************************************************/

OK, I can see a line close to the end that says:

extern MCP_CAN CAN;

But I'm wondering if the "extern" keyword is making it think that the object is actually going to be created somewhere else.

You could try adding this to your sketch before void setup(), and leaving the header file as it is.

MCP_CAN CAN;

By the way, it's better when posting code in the forum to use the code tags - there is a button marked "#" above the row of smileys. It makes the posts easier to read :slight_smile:

All the best

Ray

Hello,

Thanks again for all your help, after doing a bit more hunting online i found a sketch that would compile.
I have done my best to pull that one apart and add it to the one i wanted to work.

This might be a little crude and might not even work, but it dose compile and up load and the serial monitor looks good.
I am at work now and can not do a full test on the can bus outputs but fingers crossed:

See what you think (feel free to point out any really stupid mistakes)

#include <SoftwareSerial.h>
#include <mcp_can.h>
#include <SPI.h>

SoftwareSerial sLCD =  SoftwareSerial(3, 6); /* Serial LCD is connected on pin 14 (Analog input 0) */
#define COMMAND 0xFE
#define CLEAR   0x01
#define LINE0   0x80
#define LINE1   0xC0

/* Define Joystick connection */
#define UP     A1
#define RIGHT  A2
#define DOWN   A3
#define CLICK  A4
#define LEFT   A5

//#define CANint 2
#define LED2 8
#define LED3 7
MCP_CAN CAN0(10);                                      

#define NOP __asm__ ("nop\n\t")

void setup() {
  Serial.begin(115200);
  Serial.println("Init...");

  sLCD.begin(9600);
  clearLCD();
  sLCD.print("RX-8 CAN control");
  sLCD.write(COMMAND);
  sLCD.write(LINE1);
  sLCD.print("www.cantanko.com");

  Serial.println("Setup pins");
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
//  pinMode(CAN0, INPUT);
  pinMode(UP,INPUT);
  pinMode(DOWN,INPUT);
  pinMode(LEFT,INPUT);
  pinMode(RIGHT,INPUT);
  pinMode(CLICK,INPUT);

  Serial.println("Enable pullups");
  digitalWrite(LED2, LOW);
  digitalWrite(UP, HIGH);       /* Enable internal pull-ups */
  digitalWrite(DOWN, HIGH);
  digitalWrite(LEFT, HIGH);
  digitalWrite(RIGHT, HIGH);
  digitalWrite(CLICK, HIGH);

  Serial.println("CAN init:");
  if (CAN0.begin(CAN_500KBPS) == CAN_OK) {
    Serial.println("OK!");
  } else {
    Serial.println("fail :-(");
    while (1) {
      Serial.print("Zzz... ");
      delay(1000);
    }
  }
  // Debug: iu

  //sLCD.begin(9600);
  //clearLCD();
  Serial.println("Good to go!");
}

unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
unsigned char otmp[8] = {255,255,255,255,255,255,255,255};
unsigned char statusPCM[8] = {125,0,0,0,156,0,0,0};
unsigned char statusMIL[8] = {140,0,0,0,0,0,0,0};
unsigned char statusDSC[8] = {0,0,0,0,0,0,0,0};
char message[17];

unsigned int i=0;
unsigned int j=0;
unsigned int pid=0;

void loop() {
  if(digitalRead(UP)==0) {
    Serial.println("PID cycling");
    for (pid=0x4B0;pid<0x500;pid++) {
      Serial.print("PID ");
      Serial.print(pid, HEX);
      Serial.println(" 0x00...");
      CAN0.sendMsgBuf(pid, 0, 8, stmp);
      delay(500);
      Serial.print("PID ");
      Serial.print(pid, HEX);
      Serial.println(" 0xFF...");
      CAN0.sendMsgBuf(pid, 0, 8, otmp);
      delay(500);
      Serial.print("PID ");
      Serial.print(pid, HEX);
      Serial.println(" 0x00...");
      CAN0.sendMsgBuf(pid, 0, 8, stmp);
      delay(500);
    }
  }

  if(digitalRead(DOWN)==0) {
    Serial.println("Down");
    while (1) {
      if (i && 0x1) CAN0.sendMsgBuf(0x201,0,8,statusPCM);
      if (i && 0xF) CAN0.sendMsgBuf(0x212,0,8,statusDSC);
      if (i && 0xF) CAN0.sendMsgBuf(0x420,0,8,statusMIL);
      if (i && 0xFFFF) {
          statusPCM[0]++;
          if (j==13) statusPCM[4]=statusPCM[0];
          if (j==14) statusPCM[4]=statusPCM[0];
          if (statusPCM[0] > 120) {
              statusPCM[0]=0;
              j++;
              switch (j) {
                case (5):
                  statusMIL[4]=1;
                  clearAndPrint("   oil pressure");
                  break;
                case (6):
                  statusMIL[4]=0;
                  clearAndPrint("No oil pressure");
                  break;
                case (7):
                  statusMIL[4]=1;
                  clearAndPrint("   oil pressure");
                  break;
                case (8):
                  statusMIL[6]=0b00000010;
                  clearAndPrint("Low water MIL");
                  break;
                case (9):
                  statusMIL[6]=0b10000000;
                  clearAndPrint("Oil presure MIL");
                  break;
                case (10):
                  statusMIL[6]=0b01000000;
                  clearAndPrint("Bat charge MIL");
                  break;
                case (11):
                  statusMIL[6]=0b00000000;
                  statusMIL[5]=0b01000000;
                  clearAndPrint("Check engine MIL");
                  break;
                case (12):
                  statusMIL[5]=0b10000000;
                  clearAndPrint("Check engine -_-");
                  break;
                case (13):
                  statusMIL[5]=0b00000000;
                  clearAndPrint("Speedo ramp");
                  break;
                case (15):
                  statusDSC[6]=0b00000100;
                  clearAndPrint("ETC Disabled");
                  break;
                case (16):
                  statusDSC[6]=0b00001000;
                  clearAndPrint("ETC Active -_-_-");
                  break;
                case (17):
                  statusDSC[5]=0b00000000;
                  statusDSC[4]=0b01000000;
                  clearAndPrint("Brake fail MIL");
                  break;
                case (18):
                  statusDSC[4]=0b00001000;
                  clearAndPrint("ABS MIL");
                  break;
                case (19):
                  statusDSC[4]=0b00000000;
                  statusDSC[3]=0b00000100;
                  clearAndPrint("DSC off");
                  break;
                case (20):
                  statusDSC[3]=0b00000000;
                  clearLCD;
                  break;
                case (21):
                  clearLCD();
                  sLCD.print("RX-8 CAN control");
                  sLCD.write(COMMAND);
                  sLCD.write(LINE1);
                  sLCD.print("www.cantanko.com");
                  break;
              }
          }
      }
      delay(30);
      i++;
    }      
  }

  if(digitalRead(LEFT)==0) {
    Serial.println("Left: RPM sweep");
    for (i=0;i<129;i++) {
      stmp[0]=i;
      stmp[4]=i;
      Serial.println(i);
      for (j=0;j<10;j++){
        CAN0.sendMsgBuf(0x201, 0, 8, stmp);
        delay(20);
      }
    }
  }

  if(digitalRead(RIGHT)==0) {
    Serial.println("Right: Fuel sweep");
    for (j=5;j<8;j++) {
      stmp[3]=0b11111111;
      for (i=0;i<256;i++) {
        stmp[j]=i;
        Serial.print("Byte ");
        Serial.print(j);
        Serial.print(" bits ");
        Serial.print(i, BIN);
        Serial.print(" value ");
        Serial.println(i);
        CAN0.sendMsgBuf(0x212, 0, 8, stmp);
        delay(500);
      }
    }
  }
}

void clearLCD(void) {
  sLCD.write(COMMAND);
  sLCD.write(CLEAR);
}

void clearAndPrint(String text) {
  clearLCD();
  sLCD.print(text);
}

Thanks for the tip on posting code too! :smiley:

I am using the can-bus shield. I am trying to run roboteQ using can bus.
The RoboteQ works with RS232 when I am using following code:

Serial2.print("!G"); // Motor GO command
Serial2.print(" "); // Space
Serial2.print("1"); // Channel Number
Serial2.print(" "); // Space
Serial2.println(x); // Motor Power Value

Serial2.print("!G"); // Motor GO command
Serial2.print(" "); // Space
Serial2.print("2"); // Channel Number
Serial2.print(" "); // Space
Serial2.println(x); // Motor Power Value

But now when I am sending the same data through CAN it does not recognize.
unsigned char roboteQ[7] = {'!','G',' ','1' ,' ', '\n', 200};
CAN.sendMsgBuf(0x01,0, 6, roboteQ);

Can someone suggest what am i doing wrong.