├── .gitignore ├── I2C_CAN_dfs.h ├── Longan_I2C_CAN_Arduino.cpp ├── Longan_I2C_CAN_Arduino.h ├── README.md ├── examples ├── OBDII_PIDs │ ├── getRpm │ │ └── getRpm.ino │ └── getSpeed │ │ ├── getSpeed.ino │ │ └── getSpeed.ino.bak ├── recv │ └── recv.ino ├── send │ └── send.ino └── set_mask_filter_recv │ └── set_mask_filter_recv.ino ├── keywords.txt └── library.properties /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /I2C_CAN_dfs.h: -------------------------------------------------------------------------------- 1 | #ifndef __I2C_CAN_DFS_H__ 2 | #define __I2C_CAN_DFS_H__ 3 | 4 | #define DEFAULT_I2C_ADDR 0X25 5 | 6 | #define REG_ADDR 0X01 7 | #define REG_DNUM 0x02 8 | #define REG_BAUD 0X03 9 | #define REG_MASK0 0X60 10 | #define REG_MASK1 0X65 11 | #define REG_FILT0 0X70 12 | #define REG_FILT1 0X80 13 | #define REG_FILT2 0X90 14 | #define REG_FILT3 0XA0 15 | #define REG_FILT4 0XB0 16 | #define REG_FILT5 0XC0 17 | 18 | #define REG_SEND 0X30 19 | #define REG_RECV 0X40 20 | 21 | #define REG_ADDR_SET 0X51 22 | 23 | 24 | #define CAN_5KBPS 1 25 | #define CAN_10KBPS 2 26 | #define CAN_20KBPS 3 27 | #define CAN_25KBPS 4 28 | #define CAN_31K25BPS 5 29 | #define CAN_33KBPS 6 30 | #define CAN_40KBPS 7 31 | #define CAN_50KBPS 8 32 | #define CAN_80KBPS 9 33 | #define CAN_83K3BPS 10 34 | #define CAN_95KBPS 11 35 | #define CAN_100KBPS 12 36 | #define CAN_125KBPS 13 37 | #define CAN_200KBPS 14 38 | #define CAN_250KBPS 15 39 | #define CAN_500KBPS 16 40 | #define CAN_666KBPS 17 41 | #define CAN_1000KBPS 18 42 | 43 | #define CAN_OK (0) 44 | #define CAN_FAILINIT (1) 45 | #define CAN_FAILTX (2) 46 | #define CAN_MSGAVAIL (3) 47 | #define CAN_NOMSG (4) 48 | #define CAN_CTRLERROR (5) 49 | #define CAN_GETTXBFTIMEOUT (6) 50 | #define CAN_SENDMSGTIMEOUT (7) 51 | #define CAN_FAIL (0xff) 52 | 53 | 54 | #endif 55 | 56 | // END FILE -------------------------------------------------------------------------------- /Longan_I2C_CAN_Arduino.cpp: -------------------------------------------------------------------------------- 1 | #include "Longan_I2C_CAN_Arduino.h" 2 | 3 | 4 | I2C_CAN::I2C_CAN(unsigned char __addr) 5 | { 6 | IIC_ADDR = __addr; 7 | } 8 | 9 | void I2C_CAN::begin() 10 | { 11 | Wire.begin(); 12 | } 13 | 14 | void I2C_CAN::IIC_CAN_SetReg(unsigned char __reg, unsigned char __len, unsigned char *__dta) 15 | { 16 | Wire.beginTransmission(IIC_ADDR); 17 | Wire.write(__reg); 18 | for(int i=0; i<__len; i++) 19 | { 20 | Wire.write(__dta[i]); 21 | } 22 | Wire.endTransmission(); 23 | 24 | } 25 | 26 | void I2C_CAN::IIC_CAN_SetReg(unsigned char __reg, unsigned char __dta) 27 | { 28 | Wire.beginTransmission(IIC_ADDR); 29 | Wire.write(__reg); 30 | Wire.write(__dta); 31 | Wire.endTransmission(); 32 | } 33 | 34 | bool I2C_CAN::IIC_CAN_GetReg(unsigned char __reg, unsigned char *__dta) 35 | { 36 | Wire.beginTransmission(IIC_ADDR); 37 | Wire.write(__reg); 38 | Wire.endTransmission(); 39 | Wire.requestFrom(IIC_ADDR, 1); 40 | 41 | while(Wire.available()) 42 | { 43 | *__dta = Wire.read(); 44 | return 1; 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | bool I2C_CAN::IIC_CAN_GetReg(unsigned char __reg, int len, unsigned char *__dta) 51 | { 52 | Wire.beginTransmission(IIC_ADDR); 53 | Wire.write(__reg); 54 | Wire.endTransmission(); 55 | Wire.requestFrom(IIC_ADDR, len); 56 | 57 | int __len = 0; 58 | 59 | while(Wire.available()) 60 | { 61 | __dta[__len++] = Wire.read(); 62 | } 63 | 64 | return (len == __len); 65 | } 66 | 67 | 68 | byte I2C_CAN::begin(byte speedset) // init can 69 | { 70 | Wire.begin(); 71 | 72 | IIC_CAN_SetReg(REG_BAUD, speedset); 73 | delay(10); 74 | 75 | unsigned char __speed = 0; 76 | 77 | if(IIC_CAN_GetReg(REG_BAUD, &__speed)) 78 | { 79 | if(speedset == __speed)return 1; 80 | 81 | } 82 | 83 | delay(100); 84 | return 0; 85 | } 86 | 87 | byte I2C_CAN::init_Mask(byte num, byte ext, unsigned long ulData) // init Masks 88 | { 89 | unsigned char dta[5]; 90 | 91 | dta[0] = ext; 92 | dta[1] = 0xff & (ulData >> 24); 93 | dta[2] = 0xff & (ulData >> 16); 94 | dta[3] = 0xff & (ulData >> 8); 95 | dta[4] = 0xff & (ulData >> 0); 96 | 97 | unsigned char mask = (num == 0) ? REG_MASK0 : REG_MASK1; 98 | 99 | IIC_CAN_SetReg(mask, 5, dta); 100 | delay(50); 101 | } 102 | 103 | byte I2C_CAN::init_Filt(byte num, byte ext, unsigned long ulData) // init filters 104 | { 105 | unsigned char dta[5]; 106 | 107 | dta[0] = ext; 108 | dta[1] = 0xff & (ulData >> 24); 109 | dta[2] = 0xff & (ulData >> 16); 110 | dta[3] = 0xff & (ulData >> 8); 111 | dta[4] = 0xff & (ulData >> 0); 112 | 113 | unsigned char filt = (7+num)*0x10; 114 | 115 | IIC_CAN_SetReg(filt, 5, dta); 116 | delay(50); 117 | } 118 | 119 | byte I2C_CAN::sendMsgBuf(unsigned long id, byte ext, byte rtr, byte len, byte *buf) // send buf 120 | { 121 | unsigned char dta[16]; 122 | 123 | dta[0] = 0xff & (id >> 24); 124 | dta[1] = 0xff & (id >> 16); 125 | dta[2] = 0xff & (id >> 8); 126 | dta[3] = 0xff & (id >> 0); 127 | 128 | dta[4] = ext; 129 | dta[5] = rtr; 130 | 131 | dta[6] = len; 132 | 133 | for(int i=0; i 0) 207 | { 208 | return CAN_MSGAVAIL; 209 | } 210 | } 211 | 212 | return 0; 213 | } 214 | 215 | byte I2C_CAN::checkError(void) // if something error 216 | { 217 | return 0; 218 | } 219 | 220 | unsigned long I2C_CAN::getCanId(void) // get can id when receive 221 | { 222 | return m_ID; 223 | } 224 | 225 | byte I2C_CAN::isRemoteRequest(void) // get RR flag when receive 226 | { 227 | return m_RTR; 228 | } 229 | 230 | byte I2C_CAN::isExtendedFrame(void) // did we recieve 29bit frame? 231 | { 232 | return m_EXT; 233 | } 234 | 235 | unsigned char I2C_CAN::makeCheckSum(unsigned char *dta, int len) 236 | { 237 | unsigned long sum = 0; 238 | for(int i=0; i 0xff) 241 | { 242 | sum = ~sum; 243 | sum += 1; 244 | } 245 | 246 | sum = sum & 0xff; 247 | return sum; 248 | } 249 | 250 | // END FILE -------------------------------------------------------------------------------- /Longan_I2C_CAN_Arduino.h: -------------------------------------------------------------------------------- 1 | #ifndef __LONGAN_I2C_CAN_ARDUINO_H__ 2 | #define __LONGAN_I2C_CAN_ARDUINO_H__ 3 | 4 | #include 5 | #include 6 | #include "I2C_CAN_dfs.h" 7 | 8 | #define MCP_CAN I2C_CAN 9 | 10 | class I2C_CAN{ 11 | 12 | private: 13 | 14 | unsigned char IIC_ADDR; 15 | unsigned long m_ID; 16 | unsigned char m_RTR; 17 | unsigned char m_EXT; 18 | 19 | unsigned char makeCheckSum(unsigned char *dta, int len); 20 | 21 | public: 22 | void begin(); 23 | void IIC_CAN_SetReg(unsigned char __reg, unsigned char __len, unsigned char *__dta); 24 | void IIC_CAN_SetReg(unsigned char __reg, unsigned char __dta); 25 | bool IIC_CAN_GetReg(unsigned char __reg, unsigned char *__dta); 26 | bool IIC_CAN_GetReg(unsigned char __reg, int len, unsigned char *__dta); 27 | 28 | public: 29 | 30 | I2C_CAN(unsigned char __addr); 31 | byte begin(byte speedset); // init can 32 | byte init_Mask(byte num, byte ext, unsigned long ulData); // init Masks 33 | byte init_Filt(byte num, byte ext, unsigned long ulData); // init filters 34 | byte sendMsgBuf(unsigned long id, byte ext, byte rtr, byte len, byte *buf); // send buf 35 | byte sendMsgBuf(unsigned long id, byte ext, byte len, byte *buf); // send buf 36 | byte readMsgBuf(byte *len, byte *buf); // read buf 37 | byte readMsgBufID(unsigned long *ID, byte *len, byte *buf); // read buf with object ID 38 | byte checkReceive(void); // if something received 39 | byte checkError(void); // if something error 40 | unsigned long getCanId(void); // get can id when receive 41 | byte isRemoteRequest(void); // get RR flag when receive 42 | byte isExtendedFrame(void); // did we recieve 29bit frame? 43 | 44 | 45 | }; 46 | 47 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Longan Labs I2C CAN Bus Module Library 2 | 3 | [![Actions Status](https://github.com/arduino/arduino-cli-example/workflows/test/badge.svg)](https://github.com/arduino/arduino-cli-example/actions) 4 | [![Spell Check](https://github.com/arduino/compile-sketches/workflows/Spell%20Check/badge.svg)](https://github.com/arduino/compile-sketches/actions?workflow=Spell+Check) 5 | [![codecov](https://codecov.io/gh/arduino/compile-sketches/branch/main/graph/badge.svg?token=Uv6f1ebMZ4)](https://codecov.io/gh/arduino/compile-sketches) 6 | 7 | We launched the Serial CAN Bus Module years ago, which is very practial and easy to use. 8 | Now we have slightly modified the Serial CAN Bus Module, wrote a special firmware, and launched this I2C CAN Bus Module. 9 | 10 | The I2C CAN Bus Module uses I2C for communication. The board is small and flexible, which make it can be quickly used in any system with an I2C interface. 11 | 12 | The I2C CAN Bus Module is based on the high-performance MCP2515 CAN Bus controller and MCP2551 CAN Bus transceiver, provides a CAN Bus communication rate of up to 1Mb/s. 13 | 14 | In addition, there is an Atmega168PA microcontroller on the board, you can also program it through a USB to Serial board, modify the firmware or write your application directly. 15 | 16 | With this library, you can, 17 | 18 | 1. Send a CAN2.0 frame 19 | 2. Receive a CAN2.0 frame 20 | 3. Get data from OBD-II 21 | 4. Set the masks and filters, there're 32 masks and filters. 22 | 23 | ## Installation 24 | 25 | 1. [Download the library](https://github.com/Longan-Labs/I2C_CAN_Arduino/archive/refs/heads/main.zip) 26 | 2. Extract the zip file 27 | 3. In the Arduino IDe, navigate to Sketch > Include Library > Add .ZIP Library 28 | 29 | ## Respository Contents 30 | 31 | * [**/examples**](./examples) - Example sketches for the library (.ino). Run these from the Arduino IDE. 32 | * [**/src**](./src) - Source files for the library (.cpp, .h). 33 | * [**keywords.txt**](./keywords.txt) - Keywords from this library that will be highlighted in the Arduino IDE. 34 | * [**library.properties**](./library.properties) - General library properties for the Arduino package manager. 35 | 36 | ## Functions 37 | 38 | - begin() 39 | - sendMsgBuf() 40 | - readMsgBuf() 41 | - readMsgBufID() 42 | - init_Mask() 43 | - init_Filt() 44 | - checkReceive() 45 | - getCanId() 46 | - isRemoteRequest() 47 | - isExtendedFrame 48 | 49 | 50 | ## Examples 51 | 52 | here are many examples implemented in this library. One of the examples is below. You can find other examples [here](./examples) 53 | 54 | ```Cpp 55 | 56 | #include 57 | 58 | #include "Longan_I2C_CAN_Arduino.h" 59 | 60 | I2C_CAN CAN(0x25); // Set CS pin 61 | 62 | void setup() 63 | { 64 | Serial.begin(115200); 65 | 66 | while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k 67 | { 68 | Serial.println("CAN BUS FAIL!"); 69 | delay(100); 70 | } 71 | Serial.println("CAN BUS OK!"); 72 | } 73 | 74 | unsigned char stmp[8] = {1, 2, 3, 4, 5, 6, 7, 0}; 75 | int cnt = 0; 76 | 77 | void loop() 78 | { 79 | stmp[7] = cnt++; 80 | if(cnt > 100)cnt = 0; 81 | 82 | CAN.sendMsgBuf(0x01, 0, 8, stmp); 83 | delay(5); // send data per 100ms 84 | } 85 | 86 | // END FILE 87 | 88 | ``` 89 | 90 | ## Get a Dev Board 91 | 92 | If you need a Dev board, plese try, 93 | 94 | - [I2C CAN Bus Module](https://www.longan-labs.cc/1030017.html) 95 | 96 | You can get others CAN Dev board below, 97 | 98 | - [Serial CAN Bus Module](https://www.longan-labs.cc/1030001.html) 99 | - [CAN Bus Shield for Arduino](https://www.longan-labs.cc/1030016.html) 100 | - [CANBed V1](https://www.longan-labs.cc/1030008.html) 101 | - [CANBed M0](https://www.longan-labs.cc/1030014.html) 102 | - [OBD-II CAN Bus GPS Dev Kit](https://www.longan-labs.cc/1030003.html) 103 | 104 | ## License 105 | 106 | ``` 107 | MIT License 108 | 109 | Copyright (c) 2018 @ Longan Labs 110 | 111 | Permission is hereby granted, free of charge, to any person obtaining a copy 112 | of this software and associated documentation files (the "Software"), to deal 113 | in the Software without restriction, including without limitation the rights 114 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 115 | copies of the Software, and to permit persons to whom the Software is 116 | furnished to do so, subject to the following conditions: 117 | 118 | The above copyright notice and this permission notice shall be included in all 119 | copies or substantial portions of the Software. 120 | 121 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 122 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 123 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 124 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 125 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 126 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 127 | SOFTWARE. 128 | ``` 129 | 130 | ## Contact us 131 | 132 | If you have any question, please feel free to contact [support@longan-labs.cc](support@longan-labs.cc) 133 | 134 | 135 | [![Analytics](https://ga-beacon.appspot.com/UA-101965714-1/I2C_CAN_Arduino)](https://github.com/igrigorik/ga-beacon) 136 | -------------------------------------------------------------------------------- /examples/OBDII_PIDs/getRpm/getRpm.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************* 2 | OBD-II_PIDs TEST CODE 3 | Loovee, Longan Labs 2022 4 | 5 | Query 6 | send id: 0x7df 7 | dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0 8 | 9 | Response 10 | From id: 0x7E9 or 0x7EA or 0x7EB 11 | dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option) 12 | 13 | https://en.wikipedia.org/wiki/OBD-II_PIDs 14 | ***************************************************************************************************/ 15 | 16 | #include 17 | #include "Longan_I2C_CAN_Arduino.h" 18 | 19 | I2C_CAN CAN(0x25); // Set I2C Address 20 | 21 | #define PID_ENGIN_PRM 0x0C 22 | #define PID_VEHICLE_SPEED 0x0D 23 | #define PID_COOLANT_TEMP 0x05 24 | 25 | #define CAN_ID_PID 0x7DF 26 | 27 | void set_mask_filt() 28 | { 29 | // set mask, set both the mask to 0x3ff 30 | 31 | CAN.init_Mask(0, 0, 0x7FC); 32 | CAN.init_Mask(1, 0, 0x7FC); 33 | 34 | // set filter, we can receive id from 0x04 ~ 0x09 35 | 36 | CAN.init_Filt(0, 0, 0x7E8); 37 | CAN.init_Filt(1, 0, 0x7E8); 38 | 39 | CAN.init_Filt(2, 0, 0x7E8); 40 | CAN.init_Filt(3, 0, 0x7E8); 41 | CAN.init_Filt(4, 0, 0x7E8); 42 | CAN.init_Filt(5, 0, 0x7E8); 43 | } 44 | 45 | void sendPid(unsigned char __pid) { 46 | unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0}; 47 | CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp); 48 | } 49 | 50 | bool getRPM(int *r) 51 | { 52 | sendPid(PID_ENGIN_PRM); 53 | unsigned long __timeout = millis(); 54 | 55 | while(millis()-__timeout < 1000) // 1s time out 56 | { 57 | unsigned char len = 0; 58 | unsigned char buf[8]; 59 | 60 | if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if get data 61 | CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf 62 | 63 | if(buf[1] == 0x41) 64 | { 65 | *r = (256*buf[3]+buf[4])/4; 66 | return 1; 67 | } 68 | } 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | void setup() 75 | { 76 | Serial.begin(9600); 77 | while(!Serial); 78 | 79 | while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k 80 | Serial.println("CAN init fail, retry..."); 81 | delay(100); 82 | } 83 | Serial.println("CAN init ok!"); 84 | set_mask_filt(); 85 | } 86 | 87 | void loop() { 88 | 89 | int __rpm = 0; 90 | 91 | int ret = getRPM(&__rpm); 92 | 93 | if(ret) 94 | { 95 | Serial.print("Engin Speed: "); 96 | Serial.print(__rpm); 97 | Serial.println(" rpm"); 98 | }else Serial.println("get Engin Speed Fail..."); 99 | 100 | delay(500); 101 | } 102 | 103 | // END FILE -------------------------------------------------------------------------------- /examples/OBDII_PIDs/getSpeed/getSpeed.ino: -------------------------------------------------------------------------------- 1 | /************************************************************************************************* 2 | OBD-II_PIDs TEST CODE 3 | Loovee, Longan Labs 2022 4 | 5 | Query 6 | send id: 0x7df 7 | dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0 8 | 9 | Response 10 | From id: 0x7E9 or 0x7EA or 0x7EB 11 | dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option) 12 | 13 | https://en.wikipedia.org/wiki/OBD-II_PIDs 14 | ***************************************************************************************************/ 15 | 16 | #include 17 | #include "Longan_I2C_CAN_Arduino.h" 18 | 19 | I2C_CAN CAN(0x25); // Set I2C Address 20 | 21 | #define PID_ENGIN_PRM 0x0C 22 | #define PID_VEHICLE_SPEED 0x0D 23 | #define PID_COOLANT_TEMP 0x05 24 | 25 | #define CAN_ID_PID 0x7DF 26 | 27 | void set_mask_filt() 28 | { 29 | // set mask, set both the mask to 0x3ff 30 | 31 | CAN.init_Mask(0, 0, 0x7FC); 32 | CAN.init_Mask(1, 0, 0x7FC); 33 | 34 | // set filter, we can receive id from 0x04 ~ 0x09 35 | 36 | CAN.init_Filt(0, 0, 0x7E8); 37 | CAN.init_Filt(1, 0, 0x7E8); 38 | 39 | CAN.init_Filt(2, 0, 0x7E8); 40 | CAN.init_Filt(3, 0, 0x7E8); 41 | CAN.init_Filt(4, 0, 0x7E8); 42 | CAN.init_Filt(5, 0, 0x7E8); 43 | } 44 | 45 | void sendPid(unsigned char __pid) { 46 | unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0}; 47 | CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp); 48 | } 49 | 50 | bool getSpeed(int *s) 51 | { 52 | sendPid(PID_ENGIN_PRM); 53 | unsigned long __timeout = millis(); 54 | 55 | while(millis()-__timeout < 1000) // 1s time out 56 | { 57 | unsigned char len = 0; 58 | unsigned char buf[8]; 59 | 60 | if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if get data 61 | CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf 62 | 63 | if(buf[1] == 0x41) 64 | { 65 | *s = buf[3]; 66 | return 1; 67 | } 68 | } 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | void setup() { 75 | Serial.begin(115200); 76 | while(!Serial); 77 | 78 | while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k 79 | Serial.println("CAN init fail, retry..."); 80 | delay(100); 81 | } 82 | Serial.println("CAN init ok!"); 83 | set_mask_filt(); 84 | } 85 | 86 | void loop() { 87 | 88 | int __speed = 0; 89 | int ret = getSpeed(&__speed); 90 | if(ret) 91 | { 92 | Serial.print("Vehicle Speed: "); 93 | Serial.print(__speed); 94 | Serial.println(" kmh"); 95 | } 96 | delay(500); 97 | } 98 | 99 | // END FILE -------------------------------------------------------------------------------- /examples/OBDII_PIDs/getSpeed/getSpeed.ino.bak: -------------------------------------------------------------------------------- 1 | /************************************************************************************************* 2 | OBD-II_PIDs TEST CODE 3 | Loovee, Longan Labs 2022 4 | 5 | Query 6 | send id: 0x7df 7 | dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0 8 | 9 | Response 10 | From id: 0x7E9 or 0x7EA or 0x7EB 11 | dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option) 12 | 13 | https://en.wikipedia.org/wiki/OBD-II_PIDs 14 | ***************************************************************************************************/ 15 | 16 | #include 17 | #include "Longan_I2C_CAN_Arduino.h" 18 | 19 | I2C_CAN CAN(0x25); // Set I2C Address 20 | 21 | #define PID_ENGIN_PRM 0x0C 22 | #define PID_VEHICLE_SPEED 0x0D 23 | #define PID_COOLANT_TEMP 0x05 24 | 25 | #define CAN_ID_PID 0x7DF 26 | 27 | void set_mask_filt() 28 | { 29 | // set mask, set both the mask to 0x3ff 30 | 31 | CAN.init_Mask(0, 0, 0x7FC); 32 | CAN.init_Mask(1, 0, 0x7FC); 33 | 34 | // set filter, we can receive id from 0x04 ~ 0x09 35 | 36 | CAN.init_Filt(0, 0, 0x7E8); 37 | CAN.init_Filt(1, 0, 0x7E8); 38 | 39 | CAN.init_Filt(2, 0, 0x7E8); 40 | CAN.init_Filt(3, 0, 0x7E8); 41 | CAN.init_Filt(4, 0, 0x7E8); 42 | CAN.init_Filt(5, 0, 0x7E8); 43 | } 44 | 45 | void sendPid(unsigned char __pid) { 46 | unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0}; 47 | CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp); 48 | } 49 | 50 | bool getSpeed(int *s) 51 | { 52 | sendPid(PID_ENGIN_PRM); 53 | unsigned long __timeout = millis(); 54 | 55 | while(millis()-__timeout < 1000) // 1s time out 56 | { 57 | unsigned char len = 0; 58 | unsigned char buf[8]; 59 | 60 | if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if get data 61 | CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf 62 | 63 | if(buf[1] == 0x41) 64 | { 65 | *s = buf[3]; 66 | return 1; 67 | } 68 | } 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | void setup() { 75 | Serial.begin(115200); 76 | while(!Serial); 77 | 78 | // below code need for OBD-II GPS Dev Kit 79 | // pinMode(A3, OUTPUT); 80 | // digitalWrite(A3, HIGH); 81 | 82 | while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k 83 | Serial.println("CAN init fail, retry..."); 84 | delay(100); 85 | } 86 | Serial.println("CAN init ok!"); 87 | set_mask_filt(); 88 | } 89 | 90 | void loop() { 91 | 92 | int __speed = 0; 93 | int ret = getSpeed(&__speed); 94 | if(ret) 95 | { 96 | Serial.print("Vehicle Speed: "); 97 | Serial.print(__speed); 98 | Serial.println(" kmh"); 99 | } 100 | delay(500); 101 | } 102 | 103 | // END FILE -------------------------------------------------------------------------------- /examples/recv/recv.ino: -------------------------------------------------------------------------------- 1 | /* receive a frame from can bus 2 | support@longan-labs.cc 3 | 4 | CAN Baudrate, 5 | 6 | #define CAN_5KBPS 1 7 | #define CAN_10KBPS 2 8 | #define CAN_20KBPS 3 9 | #define CAN_25KBPS 4 10 | #define CAN_31K25BPS 5 11 | #define CAN_33KBPS 6 12 | #define CAN_40KBPS 7 13 | #define CAN_50KBPS 8 14 | #define CAN_80KBPS 9 15 | #define CAN_83K3BPS 10 16 | #define CAN_95KBPS 11 17 | #define CAN_100KBPS 12 18 | #define CAN_125KBPS 13 19 | #define CAN_200KBPS 14 20 | #define CAN_250KBPS 15 21 | #define CAN_500KBPS 16 22 | #define CAN_666KBPS 17 23 | #define CAN_1000KBPS 18 24 | */ 25 | 26 | #include 27 | 28 | #include "Longan_I2C_CAN_Arduino.h" 29 | 30 | 31 | I2C_CAN CAN(0x25); // Set I2C Address 32 | 33 | void setup() 34 | { 35 | Serial.begin(115200); 36 | //while(!Serial); 37 | 38 | Serial.println("begin to init can"); 39 | 40 | while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k 41 | { 42 | Serial.println("CAN BUS FAIL!"); 43 | delay(100); 44 | } 45 | Serial.println("CAN BUS OK!"); 46 | pinMode(13, OUTPUT); 47 | } 48 | 49 | 50 | void loop() 51 | { 52 | unsigned char len = 0; 53 | unsigned char buf[8]; 54 | 55 | if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming 56 | { 57 | CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf 58 | 59 | if(len) 60 | { 61 | unsigned long canId = CAN.getCanId(); 62 | 63 | Serial.print("Get ID: "); 64 | Serial.println(canId, HEX); 65 | 66 | for(int i = 0; i 27 | 28 | #include "Longan_I2C_CAN_Arduino.h" 29 | 30 | 31 | I2C_CAN CAN(0x25); // Set CS pin 32 | 33 | void setup() 34 | { 35 | Serial.begin(115200); 36 | 37 | while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k 38 | { 39 | Serial.println("CAN BUS FAIL!"); 40 | delay(100); 41 | } 42 | Serial.println("CAN BUS OK!"); 43 | } 44 | 45 | unsigned char stmp[8] = {1, 2, 3, 4, 5, 6, 7, 0}; 46 | int cnt = 0; 47 | 48 | void loop() 49 | { 50 | stmp[7] = cnt++; 51 | if(cnt > 100)cnt = 0; 52 | 53 | CAN.sendMsgBuf(0x01, 0, 8, stmp); 54 | delay(5); // send data per 100ms 55 | } 56 | 57 | // END FILE 58 | -------------------------------------------------------------------------------- /examples/set_mask_filter_recv/set_mask_filter_recv.ino: -------------------------------------------------------------------------------- 1 | /* receive a frame from can bus with mask and filter setting 2 | support@longan-labs.cc 3 | 4 | CAN Baudrate, 5 | 6 | #define CAN_5KBPS 1 7 | #define CAN_10KBPS 2 8 | #define CAN_20KBPS 3 9 | #define CAN_25KBPS 4 10 | #define CAN_31K25BPS 5 11 | #define CAN_33KBPS 6 12 | #define CAN_40KBPS 7 13 | #define CAN_50KBPS 8 14 | #define CAN_80KBPS 9 15 | #define CAN_83K3BPS 10 16 | #define CAN_95KBPS 11 17 | #define CAN_100KBPS 12 18 | #define CAN_125KBPS 13 19 | #define CAN_200KBPS 14 20 | #define CAN_250KBPS 15 21 | #define CAN_500KBPS 16 22 | #define CAN_666KBPS 17 23 | #define CAN_1000KBPS 18 24 | */ 25 | 26 | #include 27 | #include "Longan_I2C_CAN_Arduino.h" 28 | 29 | I2C_CAN CAN(0x25); // Set I2C Address 30 | 31 | 32 | unsigned char flagRecv = 0; 33 | unsigned char len = 0; 34 | unsigned char buf[8]; 35 | char str[20]; 36 | 37 | void setup() 38 | { 39 | Serial.begin(115200); 40 | 41 | while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k 42 | { 43 | Serial.println("CAN BUS FAIL!"); 44 | delay(100); 45 | } 46 | Serial.println("CAN BUS OK!"); 47 | 48 | 49 | /* 50 | * set mask, set both the mask to 0x3ff 51 | */ 52 | CAN.init_Mask(0, 0, 0x7ff); // there are 2 mask in mcp2515, you need to set both of them 53 | CAN.init_Mask(1, 0, 0x7ff); 54 | 55 | /* 56 | * set filter, we can receive id from 0x04 ~ 0x09 57 | */ 58 | CAN.init_Filt(0, 0, 0x1); // there are 6 filter in mcp2515 59 | CAN.init_Filt(1, 0, 0x2); // there are 6 filter in mcp2515 60 | 61 | CAN.init_Filt(2, 0, 0x3); // there are 6 filter in mcp2515 62 | CAN.init_Filt(3, 0, 0x4); // there are 6 filter in mcp2515 63 | CAN.init_Filt(4, 0, 0x5); // there are 6 filter in mcp2515 64 | CAN.init_Filt(5, 0, 0x6); // there are 6 filter in mcp2515 65 | } 66 | 67 | void loop() 68 | { 69 | if(CAN_MSGAVAIL == CAN.checkReceive()) // check if get data 70 | { 71 | CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf 72 | 73 | if(len) 74 | { 75 | unsigned long canId = CAN.getCanId(); 76 | 77 | Serial.print("Get ID: "); 78 | Serial.println(canId, HEX); 79 | 80 | for(int i = 0; i