8 years ago.

can bus arduino mega with lpc1768

Below are examples of canbus from arduino, sender and receiver. I need to write a code how to use lpc178 as receiver. I am using the mcp2515 module. Thanks friends...

CAn send

  1. include <mcp_can.h>
  2. include <SPI.h>

MCP_CAN CAN0(53); Set CS to pin 10

void setup() { Serial.begin(115200);

Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled. if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!"); else Serial.println("Error Initializing MCP2515...");

CAN0.setMode(MCP_NORMAL); Change to normal mode to allow messages to be transmitted }

byte data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

void loop() { send data: ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send byte sndStat = CAN0.sendMsgBuf(0x100, 0, 8, data); if(sndStat == CAN_OK){ Serial.println("Message Sent Successfully!"); } else { Serial.println("Error Sending Message..."); } delay(100); send data per 100ms }

CAN Receive Example

  1. include <mcp_can.h>
  2. include <SPI.h>

long unsigned int rxId; unsigned char len = 0; unsigned char rxBuf[8]; char msgString[128]; Array to store serial string

  1. define CAN0_INT 2 Set INT to pin 2 MCP_CAN CAN0(53); Set CS to pin 10

void setup() { Serial.begin(115200);

Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled. if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!"); else Serial.println("Error Initializing MCP2515...");

CAN0.setMode(MCP_NORMAL); Set operation mode to normal so the MCP2515 sends acks to received data.

pinMode(CAN0_INT, INPUT); Configuring pin for /INT input

Serial.println("MCP2515 Library Receive Example..."); }

void loop() { if(!digitalRead(CAN0_INT)) If CAN0_INT pin is low, read receive buffer { CAN0.readMsgBuf(&rxId, &len, rxBuf); Read data: len = data length, buf = data byte(s)

if((rxId & 0x80000000) == 0x80000000) Determine if ID is standard (11 bits) or extended (29 bits) sprintf(msgString, "Extended ID: 0x%.8lX DLC: %1d Data:", (rxId & 0x1FFFFFFF), len); else sprintf(msgString, "Standard ID: 0x%.3lX DLC: %1d Data:", rxId, len);

Serial.print(msgString);

if((rxId & 0x40000000) == 0x40000000){ Determine if message is a remote request frame. sprintf(msgString, " REMOTE REQUEST FRAME"); Serial.print(msgString); } else { for(byte i = 0; i<len; i++){ sprintf(msgString, " 0x%.2X", rxBuf[i]); Serial.print(msgString); } }

Serial.println(); } }

3 Answers

8 years ago.

Hello. Mbed tools do not care (for the most part) about the target board so experiment with yours and the following available CAN examples / libraries. Select the IMPORT CODE button and select your target board inside the Compiler Window (top right side - you can add your target board from the GUI):

https://developer.mbed.org/users/tecnosys/code/mcp2515/

https://developer.mbed.org/users/FalconOnishi/code/MCP2515/

https://developer.mbed.org/questions/68586/How-to-use-MCP2515-for-LPC1114FN28/

In the future, please post with the following tags - will format your code for easier viewing:

<<code>> ; at the start of your code <</code>> ; at the end of your code

https://developer.mbed.org/users/WiredHome/notebook/can---getting-started/

Thank you so much for your suggestions . ı will write here again after tried all codes that you shared.

posted by EKREM KELES 08 Dec 2016
8 years ago.

Hello Ekrem,

To make your code nicely formatted please use the Wiki Syntax as below (see also the link to Editing tips at the bottom of your editing box for more details). It becomes much easier to read.

<<code>>
int max(int x, int y) {
    return (x > y) ? x : y;
}
<</code>>


Your Arduino CAN sender code formatted:

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

MCP_CAN CAN0(53);  // Set CS to pin 10

void setup() { 
    Serial.begin(115200); // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled. 
    
    if(CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) 
        Serial.println("MCP2515 Initialized Successfully!"); 
    else 
        Serial.println("Error Initializing MCP2515...");

    CAN0.setMode(MCP_NORMAL);  // Change to normal mode to allow messages to be transmitted }
}

byte data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

void loop() {  
    // send data: ID = 0x100, Standard CAN Frame, Data length = 8 bytes, 'data' = array of data bytes to send byte 
    sndStat = CAN0.sendMsgBuf(0x100, 0, 8, data); 

    if(sndStat == CAN_OK)
        Serial.println("Message Sent Successfully!"); 
    else 
        Serial.println("Error Sending Message...");
 
    delay(100);  //send data per 100ms
}



An example of receiver code for LPC1768 board (see also the mbed CAN-Handbook for more info):

#include "mbed.h"
 
const uint16_t MSG_ID = 0x100;

Serial      pc(USBTX, USBRX);
DigitalOut  led1(LED1);
CAN         can(p30, p29);
CANMessage  msg;
 
int main()
{
    can.frequency(500000);
 
    while(1) {
        if(can.read(msg)) {
            pc.printf("CAN message received\r\n");
            pc.printf("  ID      = 0x%.3x\r\n", msg.id);
            pc.printf("  Type    = %d\r\n", msg.type);
            pc.printf("  Format  = %d\r\n", msg.format);
            pc.printf("  Length  = %d\r\n", msg.len);
            pc.printf("  Data    =");            
            for(int i = 0; i < msg.len; i++)
                pc.printf(" %.2x", msg.data[i]);
            pc.printf("\r\n");

            if(msg.id == MSG_ID) {
                led1 = !led1;
            }
        }
    }
}


Schematic (Zoom in) /media/uploads/hudakz/can_arduino_mbed_lpc1768_03.png

NOTE: Since in the example above the receiver is sending data to the connected PC over a 'slow' serial connection I recommend to increase the Arduino's send delay from 100ms to 1000ms or more.

Zoltan

hi Zoltan Thank you so much for your suggestions . ı was tried that code ago. but ı will try again. ı made that send candata -receive can data by using arduino. ı send data by arduino on MCP2515 Module and ı try read data from canbus line by lpc1768 contoller and mcp2551Integrated .But ı cant read data on cabus line with using lpc1768.

ı using can frequency(125000) .and baudrate is 9600 to see data.

ı think ı have small wrong about data type convert but ı dont know what it is . ı send data type : data id = unsigned char and data =unsigned char . ı read data type is data id = const uint16_t . ı cant know how ı will use that function well :

CANMessage(int _id, const char *_data, char _len=8, CANType _type= CANData, CANFormat _format =CANStandart)

but ı will try use these codes again.

posted by EKREM KELES 08 Dec 2016

I see the picture you sent but I use the mcp2515 module, I do not use integrated 2515 and 2551. I only use 2551 for lpc1768. Because there are 2515 and 2551 for the MCP2515 CANBUS-SPI Communication Module.

posted by EKREM KELES 08 Dec 2016

Hello Ekrem,
The MCP2515 chip (the one connected to the Arduino) is just a stand-alone CAN controller with SPI interface. If you connect it directly to a CAN bus it will not work. An additional CAN transceiver (like for example the MCP2551) is needed for such connection. If you use an Arduino shield, for instance this https://www.sparkfun.com/products/13262 or this http://wiki.seeed.cc/CAN-BUS_Shield_V1.2/ then both chips (MCP2515 + MCP2551) are already installed. Otherwise, when you build a CAN interface for Arduino by yourself, you have to add both chips as indicated on the schematic above.

posted by Zoltan Hudak 08 Dec 2016

Thank you sir, if I can create a CANbus line like the picture you sent me, can I solve this problem?

posted by EKREM KELES 08 Dec 2016
8 years ago.

/media/uploads/satoglu/can_bus1.png

hii Zoltan, we use the circuit so that. we use MCP2515 CANBUS Modul between arduino and canbus line. also there is in mcp2551 and mcp2515 inside canbus 2515 Module.

WikiPage http://www.google.com.tr/search?q=canbu+module&espv=2&biw=1366&bih=589&source=lnms&tbm=isch&sa=X&ved=0ahUKEwjl3PfrxeXQAhVrBsAKHYgrDBUQ_AUIBygC#imgrc=NorJfTLa58Mr7M%3A

are you mean we cant can-bus communicate between using arduino and lpc1768 ? do we need buy things (canbus shield) what you shared links?

Hello,
The CAN module (shield) you use is equipped with a TJA1050 CAN transceiver which provides the same functionality as MCP2551. So you do not need to buy anything else. Your schematic (in the picture above) is correct and the CAN bus communication between arduino and LPC1768 shall work.
NOTE: Make sure that the arduino's GND is also connected to the same GND as the CAN modules, LPC1768 and MCP2551 (I could not see this connection in your schematic).

posted by Zoltan Hudak 09 Dec 2016

thank you. For a month we try the codes above and our connections are correct. But we can not read lpc1768 den message, I think we have a programmatic error. What else could be wrong?

posted by EKREM KELES 10 Dec 2016

I have tested the code above with LPC1768 and it works fine. For Arduino I use this CAN bus library. It shall work also with your CAN module. Once downloaded, unzip the arduinoCANBUS-library-v0_3.zip file. The library is implemented in the arduinoCAN.h and arduinoCAN.cpp files. There are also some good examples attached. For installation instructions have a look at this link. Before using it remember to configure the CAN_CS pin in the arduinoCAN.h file according to your schematic (#define CAN_CS 10). Interrupt (CAN_INT pin) is not used. Also make sure you set-up the same CAN bus frequency for both the Arduino module and the LPC1768. For example, if you would like to use 250kbps then:

Arduino

...
void setup() {
    myCAN.begin(250);
...
}


LPC1768

...
int main()
{
    myCAN.frequency(250000);
...
}


NOTE: Although this Question does not relate to Arduino, it might be useful to have a look.

posted by Zoltan Hudak 10 Dec 2016

Hello, yes we managed to run it, but arduino is 500 kbps, lpc can.frequency (250000), but we read like this. What could be the reason for this?

posted by EKREM KELES 11 Dec 2016

arduinomega2560;

#include <mcp_can.h>
#include <SPI.h>
 //11 ok 12 error
 const int SPI_CS_PIN = 53; //Can‐Bus pin ayarı
 MCP_CAN CAN(SPI_CS_PIN);
 const int analogInPin =0; // Ldr Pin Ayarı
int sensorValue = 0;
   char outputValue = 0;
 void setup()
 {
Serial.begin(9600);
 pinMode(5,OUTPUT);
 pinMode(6,OUTPUT);
 START_INIT:
 if(CAN_OK == CAN.begin(CAN_500KBPS)) //Can‐Bus bağlantı hızı ve kontrolü
 {
 Serial.println("CAN BUS Shield init ok!");
 digitalWrite(6,LOW);
 digitalWrite(5,HIGH); //Baglanti Kuruldu Ledi
 }
 else
 {
 Serial.println("CAN BUS Shield init fail");
 Serial.println("Init CAN BUS Shield again");


 digitalWrite(5,LOW);
 digitalWrite(6,HIGH); //Baglanti Kuruldu Ledi
 delay(1000);
 goto START_INIT;
 }
 }
 void loop()
 {
 sensorValue = analogRead(analogInPin); // sensör okuma
 outputValue = map(sensorValue, 0, 1023, 0, 255);
 analogWrite(3,outputValue);
  byte ldr[8] = {outputValue, 0, 0, 0, 0, 0, 0, 0};
 // send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
 CAN.sendMsgBuf(0x001,0, 8, ldr); //Can‐Bus hattına veri gönderme
delay(1000);
 }
posted by EKREM KELES 11 Dec 2016

/media/uploads/kelesekrem/ekran_al-nt-s-.png

posted by EKREM KELES 11 Dec 2016

lpc1768 receiver;

#include "mbed.h"
 
const uint16_t MSG_ID = 0x001;
 
Serial      pc(USBTX, USBRX);
DigitalOut  led1(LED1);
DigitalOut  led2(LED2);
CAN         can(p30, p29);
//CANMessage  msg;
   CANMessage msg = CANMessage();                            /*Variable de type CANMessage*/
   
          //canmsg.id=0x001;                    /*L'identification du message*/
       
int main()
{
    can.frequency(250000);
    pc.baud(9600);
  msg.len=8;                       /*Longeur de la trame en octet*/
        msg.format=CANStandard;          /*Format de la trame CANStandart 11 octet*/
        msg.type=CANData; 
    while(1) {
        if(can.read(msg)) {
            led2.write(1);
            pc.printf("CAN message received\r\n");
            pc.printf("  ID      = 0x%.3x\r\n", msg.id);
            pc.printf("  Type    = %d\r\n", msg.type);
            pc.printf("  Format  = %d\r\n", msg.format);
            pc.printf("  Length  = %d\r\n", msg.len);
            pc.printf("  Data    =");            
            for(int i = 0; i < msg.len; i++){
                pc.printf(" %.2x", msg.data[i]);
            pc.printf("\r\n");
 }
            if(msg.id == MSG_ID) {
                led1 = !led1;
            }
        }
    }
}

posted by EKREM KELES 11 Dec 2016

Hello,
I had a closer look at the CAN bus module you are using and it seems (at least based on the picture on the AliExpress site ) that it's equipped with an 8MHz crystal (however, the Arduino library assumes 16MHz by default). That could explain why the CAN bus frequency is shifted two times.

Try to initialize the CAN bus with 8MHz crystal:

void setup() {

...

if(CAN_OK == CAN.begin(MCP_ANY, CAN_250KBPS, MCP_8MHZ)) {

...

}
posted by Zoltan Hudak 11 Dec 2016

Thank you. The library we use does not accept this encoding. It's not important, we're doing it. We are tired of you too, but sorry.. I am sending the following code to Arduino,

sensorValue = analogRead(A0); sensör okuma outputValue = map(sensorValue, 0, 1023, 0, 255); byte data[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, outputValue};

but lpc1768 reads it with 16 bits of data. I want to read 0-1023 or 0-255. How can we do this?

posted by EKREM KELES 12 Dec 2016

You can send various data types over CAN bus for example as follows:

Arduino code

...
const unsigned int  ID_SENSOR_VALUE = 0x201;
const unsigned int  ID_OUTPUT_VALUE = 0x202;
const unsigned int  ID_SENSOR_VOLTAGE = 0x203;
...
union CanDataType {
    byte  			data[8];		// 8 bytes (max length)
    unsigned int	sensorValue;	// 2 bytes
    char  			outputValue;	// 1 byte
    float 			sensorVoltage;	// 4 bytes
};
...
CanDataType  canData;
unsigned int sensorValue;           // 2 bytes
byte         outputValue;           // 1 byte
float        sensorVoltage;         // 4 bytes
...
void loop() {
    ...
    sensorValue = analogRead(analogInPin);
    outputValue = map(sensorValue, 0, 1023, 0, 255);
    sensorVoltage = (sensorValue * 5) / 1023.0f;
    ...
    canData.sensorValue = sensorValue;
    CAN.sendMsgBuf(ID_SENSOR_VALUE , 0, sizeof(canData.sensorValue), &canData);
    delay(1000);
    canData.outputValue = outputValue;
    CAN.sendMsgBuf(ID_OUTPUT_VALUE, 0, sizeof(canData.outputValue), &canData);
    delay(1000);
    canData.sensorVoltage = sensorVoltage;
    CAN.sendMsgBuf(ID_SENSOR_VOLTAGE, 0, sizeof(canData.sensorVoltage), &canData);
    delay(1000);
}


LPC1768 code

#include "mbed.h"
 
const uint16_t ID_SENSOR_VALUE = 0x201;
const uint16_t ID_OUTPUT_VALUE = 0x202;
const uint16_t ID_SENSOR_VOLTAGE = 0x203;
 
Serial       pc(USBTX, USBRX);
DigitalOut   led1(LED1);
DigitalOut   led2(LED2);
CAN          can(p30, p29);
CANMessage   msg;
uint16_t     sensorValue;	// 2 bytes		
uint8_t      outputValue;	// 1 byte
float        sensorVoltage;	// 4 bytes
       
int main()
{
    pc.baud(9600);
    can.frequency(250000);

    while(1) {
        if(can.read(msg)) {
            led1 = !led1;
            pc.printf("CAN message received\r\n");
            pc.printf("  ID      = 0x%.3x\r\n", msg.id);
            pc.printf("  Type    = %d\r\n", msg.type);
            pc.printf("  Format  = %d\r\n", msg.format);
            pc.printf("  Length  = %d\r\n", msg.len);
            pc.printf("  Data    =");
			            
            for(int i = 0; i < msg.len; i++){
                pc.printf(" 0x%.2x", msg.data[i]);
            }
            
            pc.printf("\r\n");
            
			switch(msg.id) {
	        case ID_SENSOR_VALUE:
				sensorValue = *((uint16_t*)msg.data);
				pc.printf("sensorValue = %d\r\n", sensorValue);
		        break;
	        case ID_OUTPUT_VALUE:
				outputValue = *((uint8_t*)msg.data);
				pc.printf("outputValue = %d\r\n", outputValue);
		        break;
	        case ID_SENSOR_VOLTAGE:
				sensorVoltage = *((float*)msg.data);
				pc.printf("sensorVoltage = %5.3fV\r\n", sensorVoltage);
		        break;
	        }
		}		
    }
}
posted by Zoltan Hudak 12 Dec 2016

Hello Zoltan, Thank you so so much for your help.we have learned our wrong and we have learned canbus communication because of you . he can do all canbus communication after someone looked that sharing. kind regards

posted by ibrahim SATOGLU 14 Dec 2016

Hello Zoltan ,ı have one question more. how can ı read negative value on canbus line. for example the sensor read -5 value of data and send that to canbus lıne . but ı read 250 on lpc1768. ı send data of sensor value by "char"

send canbus data

signed char ldr[8] = {val2, 0, 0, 0, 0, 0, 0, 0}; // send data to canbus line
posted by ibrahim SATOGLU 25 Dec 2016

Hello,
Computers encode signed integers as two's complement. If you receive a byte with bits coded such way and interpret it as unsigned char (uint8_t) then you will get wrong results. When you send a signed char then you also have to interpret the received data as signed char (int8_t). So instead of declaring the variable as uint8_t declare it as int8_t and also remember to cast it to int8_t as below:

LPC1768

...
int8_t  outputValue;   // 1byte
...
            case ID_OUTPUT_VALUE:
                outputValue = *((int8_t*)msg.data);
                pc.printf("outputValue = %d\r\n", outputValue);
                break;
...
posted by Zoltan Hudak 25 Dec 2016