diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..6612607 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [sandeepmistry] diff --git a/.travis.yml b/.travis.yml index d4fb702..418faf1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,16 @@ env: - IDE_VERSION=1.8.5 matrix: - BOARD="arduino:avr:uno" + - BOARD="arduino:samd:mkrzero" - BOARD="espressif:esp32:esp32" before_install: - wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz - tar xf arduino-$IDE_VERSION-linux64.tar.xz - mv arduino-$IDE_VERSION $HOME/arduino-ide - export PATH=$PATH:$HOME/arduino-ide + - if [[ "$BOARD" =~ "arduino:samd:" ]]; then + arduino --install-boards arduino:samd; + fi - if [[ "$BOARD" =~ "espressif:esp32:" ]]; then mkdir -p $HOME/Arduino/hardware/espressif; git clone https://github.com/espressif/arduino-esp32.git $HOME/Arduino/hardware/espressif/esp32; @@ -18,7 +22,6 @@ before_install: popd; fi - buildExampleSketch() { arduino --verbose-build --verify --board $BOARD $PWD/examples/$1/$1.ino; } - - buildExampleOBDIISketch() { arduino --verbose-build --verify --board $BOARD $PWD/examples/OBDII/$1/$1.ino; } install: - mkdir -p $HOME/Arduino/libraries - ln -s $PWD $HOME/Arduino/libraries/CAN @@ -26,6 +29,3 @@ script: - buildExampleSketch CANReceiver - buildExampleSketch CANReceiverCallback - buildExampleSketch CANSender - - buildExampleOBDIISketch EngineRPM - - buildExampleOBDIISketch SupportedPIDs - - buildExampleOBDIISketch VINReader diff --git a/README.md b/README.md index ab5350e..cf4b798 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ An Arduino library for sending and receiving data using CAN bus. ## Compatible Hardware * [Microchip MCP2515](http://www.microchip.com/wwwproducts/en/en010406) based boards/shields + * [Arduino MKR CAN shield](https://store.arduino.cc/arduino-mkr-can-shield) * [Espressif ESP32](http://espressif.com/en/products/hardware/esp32/overview)'s built-in [SJA1000](https://www.nxp.com/products/analog/interfaces/in-vehicle-network/can-transceiver-and-controllers/stand-alone-can-controller:SJA1000T) compatible CAN controller with an external 3.3V CAN transceiver ### Microchip MCP2515 wiring @@ -22,7 +23,7 @@ An Arduino library for sending and receiving data using CAN bus. | INT | 2 | -`CS` and `INT` pins can be changed by using `CAN.setPins(cs, irq)`. `INT` pin is optional, it is only needed for receive callback mode. If `INT` pin is used, it **must** be interrupt capable via [`attachInterrupt(...)`](https://www.arduino.cc/en/Reference/AttachInterrupt). +`CS` and `INT` pins can be changed by using `CAN.setPins(cs, irq)`. `INT` pin is optional, it is only needed for receive callback mode. If `INT` pin is used, it **must** be interrupt capable via [`attachInterrupt(...)`](https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/). **NOTE**: Logic level converters must be used for boards which operate at 3.3V. @@ -34,8 +35,8 @@ Requires an external 3.3V CAN transceiver, such as a [TI SN65HVD230](http://www. | :-------------: | :---: | | 3V3 | 3V3 | | GND | GND | -| CTX | 5 | -| CRX | 4 | +| CTX | GPIO_5 | +| CRX | GPIO_4 | `CTX` and `CRX` pins can be changed by using `CAN.setPins(rx, tx)`. @@ -63,6 +64,8 @@ See [API.md](API.md). See [examples](examples) folder. +For OBD-II examples, checkout the [arduino-OBD2](https://github.com/sandeepmistry/arduino-OBD2) library's [examples](https://github.com/sandeepmistry/arduino-OBD2/examples). + ## License This library is [licensed](LICENSE) under the [MIT Licence](http://en.wikipedia.org/wiki/MIT_License). diff --git a/examples/CANReceiver/CANReceiver.ino b/examples/CANReceiver/CANReceiver.ino index fca49e4..d2f5db8 100644 --- a/examples/CANReceiver/CANReceiver.ino +++ b/examples/CANReceiver/CANReceiver.ino @@ -20,7 +20,7 @@ void loop() { // try to parse packet int packetSize = CAN.parsePacket(); - if (packetSize) { + if (packetSize || CAN.packetId() != -1) { // received a packet Serial.print("Received "); diff --git a/examples/OBDII/EngineRPM/EngineRPM.ino b/examples/OBDII/EngineRPM/EngineRPM.ino deleted file mode 100644 index b1b8702..0000000 --- a/examples/OBDII/EngineRPM/EngineRPM.ino +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// -// -// This examples queries the engine RPM (OBD-II PID 0x0c) once a seconds and -// prints the value to the serial monitor -// -#include - -// Most cars support 11-bit adddress, others (like Honda), -// require 29-bit (extended) addressing, set the next line -// to true to use extended addressing -const bool useStandardAddressing = true; - -void setup() { - Serial.begin(9600); - - Serial.println("CAN OBD-II engine RPM"); - - // start the CAN bus at 500 kbps - if (!CAN.begin(500E3)) { - Serial.println("Starting CAN failed!"); - while (1); - } - - // add filter to only receive the CAN bus ID's we care about - if (useStandardAddressing) { - CAN.filter(0x7e8); - } else { - CAN.filterExtended(0x18daf110); - } -} - -void loop() { - if (useStandardAddressing) { - CAN.beginPacket(0x7df, 8); - } else { - CAN.beginExtendedPacket(0x18db33f1, 8); - } - CAN.write(0x02); // number of additional bytes - CAN.write(0x01); // show current data - CAN.write(0x0c); // engine RPM - CAN.endPacket(); - - // wait for response - while (CAN.parsePacket() == 0 || - CAN.read() < 3 || // correct length - CAN.read() != 0x41 || // correct mode - CAN.read() != 0x0c); // correct PID - - float rpm = ((CAN.read() * 256.0) + CAN.read()) / 4.0; - - Serial.print("Engine RPM = "); - Serial.println(rpm); - - delay(1000); -} diff --git a/examples/OBDII/SupportedPIDs/SupportedPIDs.ino b/examples/OBDII/SupportedPIDs/SupportedPIDs.ino deleted file mode 100644 index 94012b4..0000000 --- a/examples/OBDII/SupportedPIDs/SupportedPIDs.ino +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// -// -// This examples queries the ECU for the Mode 01 OBD-II PID's it supports and prints the supported -// OBD-II PID's to the serial monitor -// -// A full list of PID's and their meaning can be found here: -// https://en.wikipedia.org/wiki/OBD-II_PIDs#Mode_01 -// -#include - -// Most cars support 11-bit adddress, others (like Honda), -// require 29-bit (extended) addressing, set the next line -// to true to use extended addressing -const bool useStandardAddressing = true; - -void setup() { - Serial.begin(9600); - - Serial.println("CAN OBD-II supported pids"); - - // start the CAN bus at 500 kbps - if (!CAN.begin(500E3)) { - Serial.println("Starting CAN failed!"); - while (1); - } - - // add filter to only receive the CAN bus ID's we care about - if (useStandardAddressing) { - CAN.filter(0x7e8); - } else { - CAN.filterExtended(0x18daf110); - } -} - -void loop() { - for (int pid = 0x00; pid < 0xe0; pid += 0x20) { - if (useStandardAddressing) { - CAN.beginPacket(0x7df, 8); - } else { - CAN.beginExtendedPacket(0x18db33f1, 8); - } - CAN.write(0x02); // number of additional bytes - CAN.write(0x01); // show current data - CAN.write(pid); // PID - CAN.endPacket(); - - // wait for response - while (CAN.parsePacket() == 0 || - CAN.read() < 6 || // correct length - CAN.read() != 0x41 || // correct mode - CAN.read() != pid); // correct PID - - unsigned long pidsSupported = 0; - - for (int i = 0; i < 4; i++) { - pidsSupported <<= 8; - pidsSupported |= CAN.read(); - } - - for (unsigned int i = 31; i > 0; i--) { - if (pidsSupported & (1UL << i)) { - int pidSupported = pid + (32 - i); - - Serial.print("0x"); - if (pidSupported < 16) { - Serial.print("0"); - } - Serial.println(pidSupported, HEX); - } - } - - if ((pidsSupported & 0x00000001) == 0x00000000) { - // next round not supported, all done - break; - } - } - - Serial.println("That's all folks!"); - - while (1); // all done -} diff --git a/examples/OBDII/VINReader/VINReader.ino b/examples/OBDII/VINReader/VINReader.ino deleted file mode 100644 index e620b33..0000000 --- a/examples/OBDII/VINReader/VINReader.ino +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) Sandeep Mistry. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// -// -// This examples queries the ECU for the car's Vehicle Identification Number (VIN) and -// prints it out to the serial monitor using Mode 09 and OBD-II PID 0x02 -// -#include - -// Most cars support 11-bit adddress, others (like Honda), -// require 29-bit (extended) addressing, set the next line -// to true to use extended addressing -const bool useStandardAddressing = true; - -void setup() { - Serial.begin(9600); - - Serial.println("CAN OBD-II VIN reader"); - - // start the CAN bus at 500 kbps - if (!CAN.begin(500E3)) { - Serial.println("Starting CAN failed!"); - while (1); - } - - // add filter to only receive the CAN bus ID's we care about - if (useStandardAddressing) { - CAN.filter(0x7e8); - } else { - CAN.filterExtended(0x18daf110); - } -} - -void loop() { - // send the request for the first chunk - if (useStandardAddressing) { - CAN.beginPacket(0x7df, 8); - } else { - CAN.beginExtendedPacket(0x18db33f1, 8); - } - CAN.write(0x02); // Number of additional bytes - CAN.write(0x09); // Request vehicle information - CAN.write(0x02); // Vehicle Identification Number (VIN) - CAN.endPacket(); - - // wait for response - while (CAN.parsePacket() == 0 || - CAN.read() != 0x10 || CAN.read() != 0x14 || // correct length - CAN.read() != 0x49 || // correct mode - CAN.read() != 0x02 || // correct PID - CAN.read() != 0x01); - - // print out - while (CAN.available()) { - Serial.write((char)CAN.read()); - } - - // read in remaining chunks - for (int i = 0; i < 2; i++) { - // send the request for the next chunk - if (useStandardAddressing) { - CAN.beginPacket(0x7e0, 8); - } else { - CAN.beginExtendedPacket(0x18db33f1, 8); - } - CAN.write(0x30); - CAN.endPacket(); - - // wait for response - while (CAN.parsePacket() == 0 || - CAN.read() != (0x21 + i)); // correct sequence number - - // print out - while (CAN.available()) { - Serial.write((char)CAN.read()); - } - } - - Serial.println("That's all folks!"); - - while (1); // all done -} diff --git a/library.properties b/library.properties index 6810f13..acf321f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=CAN -version=0.2.0 +version=0.3.1 author=Sandeep Mistry maintainer=Sandeep Mistry sentence=An Arduino library for sending and receiving data using CAN bus. diff --git a/src/ESP32SJA1000.cpp b/src/ESP32SJA1000.cpp index 835628e..309e030 100644 --- a/src/ESP32SJA1000.cpp +++ b/src/ESP32SJA1000.cpp @@ -111,21 +111,10 @@ int ESP32SJA1000Class::begin(long baudRate) modifyRegister(REG_BTR0, 0x3f, 49); break; - case (long)40E3: - modifyRegister(REG_BTR1, 0x0f, 0x0c); - modifyRegister(REG_BTR0, 0x3f, 62); - break; - - case (long)20E3: - modifyRegister(REG_BTR1, 0x0f, 0x0c); - modifyRegister(REG_BTR0, 0x3f, 124); - break; - - case (long)10E3: - modifyRegister(REG_BTR1, 0x0f, 0x0c); - modifyRegister(REG_BTR0, 0x3f, 249); - break; - +/* + Due to limitations in ESP32 hardware and/or RTOS software, baudrate can't be lower than 50kbps. + See https://esp32.com/viewtopic.php?t=2142 +*/ default: return 0; break; @@ -144,7 +133,6 @@ int ESP32SJA1000Class::begin(long baudRate) writeRegister(REG_AMRn(2), 0xff); writeRegister(REG_AMRn(3), 0xff); - modifyRegister(REG_OCR, 0x03, 0x02); // normal output mode // reset error counters writeRegister(REG_TXERR, 0x00); @@ -316,12 +304,12 @@ int ESP32SJA1000Class::filterExtended(long id, long mask) writeRegister(REG_ACRn(0), id >> 21); writeRegister(REG_ACRn(1), id >> 13); writeRegister(REG_ACRn(2), id >> 5); - writeRegister(REG_ACRn(3), id << 5); + writeRegister(REG_ACRn(3), id << 3); writeRegister(REG_AMRn(0), mask >> 21); writeRegister(REG_AMRn(1), mask >> 13); writeRegister(REG_AMRn(2), mask >> 5); - writeRegister(REG_AMRn(3), (mask << 5) | 0x1f); + writeRegister(REG_AMRn(3), (mask << 3) | 0x1f); modifyRegister(REG_MOD, 0x17, 0x00); // normal diff --git a/src/MCP2515.cpp b/src/MCP2515.cpp index 7e739ae..36c160d 100644 --- a/src/MCP2515.cpp +++ b/src/MCP2515.cpp @@ -91,6 +91,7 @@ int MCP2515Class::begin(long baudRate) uint8_t cnf[3]; } CNF_MAPPER[] = { { (long)8E6, (long)1000E3, { 0x00, 0x80, 0x00 } }, + { (long)8E6, (long)666666, { 0xC0, 0xB8, 0x01 } }, { (long)8E6, (long)500E3, { 0x00, 0x90, 0x02 } }, { (long)8E6, (long)250E3, { 0x00, 0xb1, 0x05 } }, { (long)8E6, (long)200E3, { 0x00, 0xb4, 0x06 } }, @@ -104,6 +105,7 @@ int MCP2515Class::begin(long baudRate) { (long)8E6, (long)5E3, { 0x1f, 0xbf, 0x07 } }, { (long)16E6, (long)1000E3, { 0x00, 0xd0, 0x82 } }, + { (long)16E6, (long)666666, { 0xC0, 0xF8, 0x81 } }, { (long)16E6, (long)500E3, { 0x00, 0xf0, 0x86 } }, { (long)16E6, (long)250E3, { 0x41, 0xf1, 0x85 } }, { (long)16E6, (long)200E3, { 0x01, 0xfa, 0x87 } }, @@ -187,15 +189,24 @@ int MCP2515Class::endPacket() writeRegister(REG_TXBnCTRL(n), 0x08); + bool aborted = false; + while (readRegister(REG_TXBnCTRL(n)) & 0x08) { if (readRegister(REG_TXBnCTRL(n)) & 0x10) { // abort + aborted = true; + modifyRegister(REG_CANCTRL, 0x10, 0x10); } yield(); } + if (aborted) { + // clear abort command + modifyRegister(REG_CANCTRL, 0x10, 0x00); + } + modifyRegister(REG_CANINTF, FLAG_TXnIF(n), 0x00); return (readRegister(REG_TXBnCTRL(n)) & 0x70) ? 0 : 1; @@ -344,8 +355,8 @@ int MCP2515Class::filterExtended(long id, long mask) int MCP2515Class::observe() { - writeRegister(REG_CANCTRL, 0x80); - if (readRegister(REG_CANCTRL) != 0x80) { + writeRegister(REG_CANCTRL, 0x60); + if (readRegister(REG_CANCTRL) != 0x60) { return 0; } @@ -433,7 +444,7 @@ void MCP2515Class::handleInterrupt() return; } - while (parsePacket()) { + while (parsePacket() || _rxId != -1) { _onReceive(available()); } } diff --git a/src/MCP2515.h b/src/MCP2515.h index f3d97bc..2f0444f 100644 --- a/src/MCP2515.h +++ b/src/MCP2515.h @@ -11,8 +11,15 @@ #include "CANController.h" #define MCP2515_DEFAULT_CLOCK_FREQUENCY 16e6 + +#if defined(ARDUINO_ARCH_SAMD) && defined(PIN_SPI_MISO) && defined(PIN_SPI_MOSI) && defined(PIN_SPI_SCK) && (PIN_SPI_MISO == 10) && (PIN_SPI_MOSI == 8) && (PIN_SPI_SCK == 9) +// Arduino MKR board: MKR CAN shield CS is pin 3, INT is pin 7 +#define MCP2515_DEFAULT_CS_PIN 3 +#define MCP2515_DEFAULT_INT_PIN 7 +#else #define MCP2515_DEFAULT_CS_PIN 10 #define MCP2515_DEFAULT_INT_PIN 2 +#endif class MCP2515Class : public CANControllerClass {