1. Introduction
- CAN stands for Controller Area Network (CAN bus). This protocol is very popular in automotive domain. In order to understand more about history, benefits, characteristics, message format of CAN, you can refer:
http://www.ni.com/white-paper/2732/en/
http://www.ti.com/lit/an/sloa101b/sloa101b.pdf
- As you knew in Introduction to ESP32, ESP32 also supports CAN interface. So I am going to make a demo for this with Arduino.
- In this demo, 2 ESP32 modules will be used: first module will send the string "hellocan" to second module. The second module will convert the string to upper case and respond it back to first module and first module will show the result in theTerminal.
2. Hardware
- ESP32 only supplies CAN controller. So you need CAN transceiver for this demo. I bought 2 CAN trasceivers here.
- ESP32 GPIO4 will act as CAN_Rx.
- So you can connect pins belows (ESP32_X: module ESP32 X, CAN_X: module CAN X, where X is 1 or 2 since we have 2 modules):
ESP32_1 IO5 - CAN_1 CTX
ESP32_1 IO4 - CAN_1 CRX
CAN_1 CANH - CAN_2 CANH
CAN_1 CANL - CAN_2 CANL
ESP32_2 IO5 - CAN_2 CTX
ESP32_2 IO4 - CAN_2 CRX
3. Software
- In order to make this demo, I used CAN driver which is made by Thomas Barth (Thanks Thomas :))
- Download the CAN library for ESP32 here. Unzip it and copy to "Arduino/libraries" folder.
- Source code for first ESP32 module: receiving string, converting to upper case and respond back:
- Source code for second ESP32 module: sending the string that need to be converted to upper case, receiving response and show it to Terminal
4. Result
- CAN stands for Controller Area Network (CAN bus). This protocol is very popular in automotive domain. In order to understand more about history, benefits, characteristics, message format of CAN, you can refer:
http://www.ni.com/white-paper/2732/en/
http://www.ti.com/lit/an/sloa101b/sloa101b.pdf
- As you knew in Introduction to ESP32, ESP32 also supports CAN interface. So I am going to make a demo for this with Arduino.
- In this demo, 2 ESP32 modules will be used: first module will send the string "hellocan" to second module. The second module will convert the string to upper case and respond it back to first module and first module will show the result in theTerminal.
2. Hardware
- ESP32 only supplies CAN controller. So you need CAN transceiver for this demo. I bought 2 CAN trasceivers here.
Figure: ESP32 CAn transceiver
- ESP32 GPIO5 will act as CAN_Tx.- ESP32 GPIO4 will act as CAN_Rx.
- So you can connect pins belows (ESP32_X: module ESP32 X, CAN_X: module CAN X, where X is 1 or 2 since we have 2 modules):
ESP32_1 IO5 - CAN_1 CTX
ESP32_1 IO4 - CAN_1 CRX
CAN_1 CANH - CAN_2 CANH
CAN_1 CANL - CAN_2 CANL
ESP32_2 IO5 - CAN_2 CTX
ESP32_2 IO4 - CAN_2 CRX
3. Software
- In order to make this demo, I used CAN driver which is made by Thomas Barth (Thanks Thomas :))
- Download the CAN library for ESP32 here. Unzip it and copy to "Arduino/libraries" folder.
- Source code for first ESP32 module: receiving string, converting to upper case and respond back:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <ESP32CAN.h> #include <CAN_config.h> /* the variable name CAN_cfg is fixed, do not change */ CAN_device_t CAN_cfg; void setup() { Serial.begin(115200); Serial.println("iotsharing.com CAN demo"); /* set CAN pins and baudrate */ CAN_cfg.speed=CAN_SPEED_1000KBPS; CAN_cfg.tx_pin_id = GPIO_NUM_5; CAN_cfg.rx_pin_id = GPIO_NUM_4; /* create a queue for CAN receiving */ CAN_cfg.rx_queue = xQueueCreate(10,sizeof(CAN_frame_t)); //initialize CAN Module ESP32Can.CANInit(); } void loop() { CAN_frame_t rx_frame; //receive next CAN frame from queue if(xQueueReceive(CAN_cfg.rx_queue,&rx_frame, 3*portTICK_PERIOD_MS)==pdTRUE){ //do stuff! if(rx_frame.FIR.B.FF==CAN_frame_std) printf("New standard frame"); else printf("New extended frame"); if(rx_frame.FIR.B.RTR==CAN_RTR) printf(" RTR from 0x%08x, DLC %d\r\n",rx_frame.MsgID, rx_frame.FIR.B.DLC); else{ printf(" from 0x%08x, DLC %d\n",rx_frame.MsgID, rx_frame.FIR.B.DLC); /* convert to upper case and respond to sender */ for(int i = 0; i < 8; i++){ if(rx_frame.data.u8[i] >= 'a' && rx_frame.data.u8[i] <= 'z'){ rx_frame.data.u8[i] = rx_frame.data.u8[i] - 32; } } } //respond to sender ESP32Can.CANWriteFrame(&rx_frame); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #include <ESP32CAN.h> #include <CAN_config.h> /* the variable name CAN_cfg is fixed, do not change */ CAN_device_t CAN_cfg; void setup() { Serial.begin(115200); Serial.println("iotsharing.com CAN demo"); /* set CAN pins and baudrate */ CAN_cfg.speed=CAN_SPEED_1000KBPS; CAN_cfg.tx_pin_id = GPIO_NUM_5; CAN_cfg.rx_pin_id = GPIO_NUM_4; /* create a queue for CAN receiving */ CAN_cfg.rx_queue = xQueueCreate(10,sizeof(CAN_frame_t)); //initialize CAN Module ESP32Can.CANInit(); } void loop() { CAN_frame_t rx_frame; //receive next CAN frame from queue if(xQueueReceive(CAN_cfg.rx_queue,&rx_frame, 3*portTICK_PERIOD_MS)==pdTRUE){ //do stuff! if(rx_frame.FIR.B.FF==CAN_frame_std) printf("New standard frame"); else printf("New extended frame"); if(rx_frame.FIR.B.RTR==CAN_RTR) printf(" RTR from 0x%08x, DLC %d\r\n",rx_frame.MsgID, rx_frame.FIR.B.DLC); else{ printf(" from 0x%08x, DLC %d\n",rx_frame.MsgID, rx_frame.FIR.B.DLC); for(int i = 0; i < 8; i++){ printf("%c\t", (char)rx_frame.data.u8[i]); } printf("\n"); } } else { rx_frame.FIR.B.FF = CAN_frame_std; rx_frame.MsgID = 1; rx_frame.FIR.B.DLC = 8; rx_frame.data.u8[0] = 'h'; rx_frame.data.u8[1] = 'e'; rx_frame.data.u8[2] = 'l'; rx_frame.data.u8[3] = 'l'; rx_frame.data.u8[4] = 'o'; rx_frame.data.u8[5] = 'c'; rx_frame.data.u8[6] = 'a'; rx_frame.data.u8[7] = 'n'; ESP32Can.CANWriteFrame(&rx_frame); } } |
Figure: ESP32 CAN demo
58 Comments
Demo 2: How to use multiple Serial ports on Arduino ESP32
http://www.iotsharing.com/2017/05/how-to-use-serial-arduino-esp32-print-debug.html
Proposed connection:
ESP32 VP231 Description
GPIO5 / GPIO12 / GPIO25 D CAN TX
GPIO4 / GPIO14 / GPIO35 R CAN RX
(xQueueReceive(CAN_cfg.rx_queue,&rx_frame, 3*portTICK_PERIOD_MS)==pdTRUE) ?
case (long)95E3:
modifyRegister(REG_BTR1, 0x0f, 0x0c);
modifyRegister(REG_BTR0, 0x3f, 25);
break;
Now this works.
sixweb
I flashed the ESP32 with the example code provided. However, it is not working. Nothing outs from the GPIO5 and GPIO4 pins. The library is not working.
Has someone successfully made it worked?
Thank you.
Thank you.
I followed your step. it works. If I plug the Can bus line to real Vehicle. I cannot receive any data. Does the code work for real vehicle
ets Jun 8 2016 00:22:57
rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:808
load:0x40078000,len:6084
load:0x40080000,len:6696
entry 0x400802e4
E (106) spiram: SPI RAM enabled but initialization failed. Bailing out.
iotsharing.com CAN demo
No things are written like "HELLOCAN".
What is the problem, what did I wrong?
I am only having the first CAN message. Where's the rest?
ID: 0x80 DLC: 0 Data: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ID: 0x80 DLC: 0 Data: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ID: 0x80 DLC: 0 Data: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
...
Should be like:
" 80";"0";"";""
"286";"8";"00 00 00 00 12 00 FE FF"
"339";"8";"00 00 00 00 00 00 9A 03"
"173";"8";"D4 7D 2A 01 25 02 24 00"
"156";"7";"FD 05 21 00 00 00 00"
"279";"8";"00 00 00 00 00 00 00 00"
" 80";"0";"";""
"286";"8";"00 00 00 00 FC FF F8 FF"
"339";"8";"00 00 00 00 00 00 9A 03"
"173";"8";"D4 7D 2A 01 25 02 24 00"
"156";"7";"FD 05 21 00 00 00 00"
"279";"8";"00 00 00 00 00 00 00 00"
Here is the simple code:
void loop() {
CAN_frame_t rx_frame;
if(xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3*portTICK_PERIOD_MS) == pdTRUE){
sprintf(msgString, "ID: 0x%.2X DLC: %1d Data: ", rx_frame.MsgID, rx_frame.FIR.B.DLC);
Serial.print(msgString);
for(int i = 0; i < 8; i++){
sprintf(dataString, "0x%.2X ", rx_frame.data.u8[i]);
Serial.print(dataString);
}
Serial.println();
}
}
Any ideas?
The resistance across the wires was 60Ω.
Thanks in advance!
As with some of the others: The example can be compiled and started via upload. It runs "error-free", but nothing happens on GPIO5! The pin shows a constant high level.
If anyone has a library that works, please provide a link.
change RX-Pin to: CAN_cfg.rx_pin_id = GPIO_NUM_35;
also try lower speed: CAN_cfg.speed=CAN_SPEED_125KBPS;
when i press buttun EN in ESP32, it show
19:32:19.051 -> ets Jun 8 2016 00:22:57
19:32:19.051 ->
19:32:19.051 -> rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
19:32:19.051 -> configsip: 0, SPIWP:0xee
19:32:19.051 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
19:32:19.051 -> mode:DIO, clock div:1
19:32:19.051 -> load:0x3fff0018,len:4
19:32:19.051 -> load:0x3fff001c,len:1044
19:32:19.051 -> load:0x40078000,len:10124
19:32:19.051 -> load:0x40080400,len:5856
19:32:19.051 -> entry 0x400806a8
19:32:19.153 -> iotsharing.com CAN demo
you want code for exemple receive can information of ECU MEGASQUIRT MS2 exemple :
ESP32 and SN65HDV230 3.3v version waveshare!
code basic:
#include
#include
CAN_device_t CAN_cfg;
int rpm;
int tps;
int kpa;
int temp;
int avance;
void setup() {
Serial.begin(115200);
Serial.println("iotsharing.com CAN demo");
Serial.print(" ID ");Serial.print(" | ");Serial.print(" RPM ");Serial.print(" | "),Serial.println("TPS");
CAN_cfg.speed=CAN_SPEED_500KBPS;
CAN_cfg.tx_pin_id = GPIO_NUM_5;
CAN_cfg.rx_pin_id = GPIO_NUM_4;
CAN_cfg.rx_queue = xQueueCreate(250,sizeof(CAN_frame_t));
//initialize CAN Module
ESP32Can.CANInit();
}
void loop() {
CAN_frame_t rx_frame;
//Serial.println("test");
//receive next CAN frame from queue
if(xQueueReceive(CAN_cfg.rx_queue,&rx_frame, 3*portTICK_PERIOD_MS)==pdTRUE){
if (rx_frame.MsgID == 1512){ // hex= 0x5F0
for(int i = 0; i < 8; i++){
if(rx_frame.data.u8[i] >= '0' && rx_frame.data.u8[i] <= '9'){
rx_frame.data.u8[i] = rx_frame.data.u8[i] - 32;
}
}
rpm = 256*rx_frame.data.u8[2]+rx_frame.data.u8[3];
tps= (256*rx_frame.data.u8[6]+ rx_frame.data.u8[7])/10;
kpa = ((256*rx_frame.data.u8[0]+ rx_frame.data.u8[1])/10);
temp = ((256*rx_frame.data.u8[4] + rx_frame.data.u8[5])/10 -32) *5/9; //CLT
//temp = ((256*msg.buf[4] + msg.buf[5])/10 -32) *5/9; //CLT
//kpa = ((256*msg.buf[0]+ msg.buf[1])/10);
Serial.print("Id: ");Serial.print(rx_frame.MsgID);Serial.print(" | ");Serial.print("Rpm: ");Serial.print(rpm);Serial.print(" | ");Serial.print("Tps: ");Serial.print(tps);
Serial.print(" | ");Serial.print("Kpa: ");Serial.print(kpa);Serial.print(" | ");Serial.print("Temp: ");Serial.println(temp);
}
if (rx_frame.MsgID == 1513){ // hex= 0x5F0
for(int i = 0; i < 8; i++){
if(rx_frame.data.u8[i] >= '0' && rx_frame.data.u8[i] <= '9'){
rx_frame.data.u8[i] = rx_frame.data.u8[i] - 32;
}
}
avance = ((256*rx_frame.data.u8[6]) + rx_frame.data.u8[7]) /10;
Serial.print("Id: ");Serial.print(rx_frame.MsgID);Serial.print(" | ");Serial.print("Avance: ");Serial.println(avance);
}
//respond to sender
//ESP32Can.CANWriteFrame(&rx_frame);
}
} // finich
the code all ok receive information, just adapt to your dream...
you have question contact me (MS2 and MS3 and offgear ECU)
Tott
Thanks iotsharring.com
/** \brief CAN configuration structure */
typedef struct {
CAN_speed_t speed; /**< \brief CAN speed. */
gpio_num_t tx_pin_id; /**< \brief TX pin. */
gpio_num_t rx_pin_id; /**< \brief RX pin. */
QueueHandle_t rx_queue; /**< \brief Handler to FreeRTOS RX queue. */
}CAN_device_t;
Hello, tested with ESP32 + SN65HVD230 module. It wasn't worked for my Astra H because the middle speed bus in GM models uses an unusual 95kbps speed. However I could figure out, in ESP32SJA1000.cpp this snipped can be added in begin() at the section "switch (baudRate)":
case (long)95E3:
modifyRegister(REG_BTR1, 0x0f, 0x0c);
modifyRegister(REG_BTR0, 0x3f, 25);
break;
Now this works.
sixweb
April 29, 2018 at 11:34 AM
Hi, I have this car, and I want to read codes from MS-CAN. I tried this code, but it is not works, can some body give the full scotch to my car, thanks :)
I want to use a Baudrate of 1000kBit/s, but the ESP is runnnin the CANBus with only 500kBit/s.
// init CAN-Bus
Serial.println("iotsharing.com CAN demo");
/* set CAN pins and baudrate */
CAN_cfg.speed=CAN_SPEED_1000KBPS;
CAN_cfg.tx_pin_id = GPIO_NUM_2; // free Pin on TTgo T-Journal
CAN_cfg.rx_pin_id = GPIO_NUM_4; // free Pin on TTgo T-Journal
/* create a queue for CAN receiving */
CAN_cfg.rx_queue = xQueueCreate(10,sizeof(CAN_frame_t));
//initialize CAN Module
ESP32Can.CANInit();
Serial.println("setup finished");
Alex
I tried the code with an old Nodemcu board (ESP32 WROM-32) and it works perfectly. If I test the code with the same Nodemcu but different ESP, i.e. with an ESP32-WROM-32E. Crashes and gets stuck at this point:
ESP32Can.CANWriteFrame(&tx_frame);
If I comment out the line it keeps running.
I use GPIO4 and 5... I also used other GPIOs, nothing changes. Flashing the bootloader, too, does nothing. The proram runs the loop twice and then nothing happens
Does somebody has any idea?
store
Im using esp32can_mirror examples and i set CAN_cfg.speed = CAN_SPEED_500KBPS
but i received data and message ID on 250KBPS its sense.
Can you help me.
architecture and interior design
commercial interior design company
blind and curtains
online florist
congratulatory flower stand
Event Design Service