CANfetti is a lightweight Arduino library designed to simplify CAN (Controller Area Network) communications across Teensy 4.x and ESP32 platforms. Whether you're sending periodic messages or building robust data logging systems, CANfetti offers a unified API that masks platform complexities.
-
Cross-Platform CAN Handling
- Automatically detects Teensy 4.x (FlexCAN) or ESP32 (TWAI) and configures the appropriate backend.
-
Simple Initialization
- Easily set up the CAN bus with a single function call, specifying your desired bit rate.
-
Versatile Frame Building
- Build standard or extended CAN frames, set the RTR flag, and manage up to 8 bytes of data.
-
Reliable Sending & Receiving
- Send and receive CAN frames with configurable timeouts. Includes built-in debug outputs for quick diagnostics.
-
Minimal Footprint
- Designed with efficiency in mind, using minimal resources while handling all core CAN operations.
-
Library Manager (Recommended)
- In the Arduino IDE, go to Sketch > Include Library > Manage Libraries...
- Search for CANfetti and click Install.
-
Manual Installation
- Clone or download CANfetti-arduino from GitHub.
- Move the
CANfetti-arduino
folder into yourDocuments/Arduino/libraries/
directory.
The CANfetti library offers three main classes:
- CANfettiManager: Manages the CAN controller (initialization, start/stop, send/receive).
- CANfettiFrame: Represents a CAN message (ID, flags, data).
- CANfetti: A helper class for building and customizing CANfettiFrame objects.
Responsible for initializing and managing CAN operations.
-
bool init(uint32_t bitrate = 500000)
Initializes the CAN controller with the specified bit rate. Returnstrue
if successful. -
void stop()
Stops the CAN controller, releasing any resources. -
bool sendMessage(const CANfettiFrame& message)
Sends a CAN message. Returnstrue
on success. -
bool receiveMessage(CANfettiFrame& message, uint32_t timeout = 0)
Attempts to receive a CAN message. Optionally specify atimeout
in milliseconds (ESP32 only). Returnstrue
if a message was received. -
bool isRunning() const
Returnstrue
if the CAN controller is currently running.
A simple container for CAN message data.
- Members
uint32_t id
: The CAN ID (standard or extended).uint8_t len
: Length of the CAN data payload (0–8).uint8_t buf[8]
: The 8-byte CAN data buffer.struct flags { bool extended; bool remote; }
: Frame type flags:extended
— settrue
for extended (29-bit) IDs.remote
— settrue
for remote transmission request (RTR) frames.
A utility class to build CANfettiFrame objects with a fluent interface.
-
CANfetti& setId(uint32_t id)
Sets the CAN ID. -
CANfetti& setExtendedFrame(bool isExtended)
Marks the frame as extended or standard. -
CANfetti& setRemoteTransmissionRequest(bool isRtr)
Marks the frame as an RTR frame iftrue
. -
CANfetti& setDataLength(uint8_t length)
Sets the length of the CAN data (up to 8). -
CANfetti& setData(const uint8_t* data, uint8_t length)
Copies the provided data into the frame buffer. Automatically caps at 8 bytes. -
CANfettiFrame build() const
Finalizes and returns the built frame.
-
Teensy 4.0 / 4.1
- Uses FlexCAN_T4.
- Automatically handled via the
USE_FLEXCAN
define.
-
ESP32
- Uses TWAI driver.
- Automatically handled via the
USE_TWAI
define.
Note: Other boards are currently not supported.
Below are minimal examples to get you started. For more detailed use cases, check out the examples folder.
#include <Arduino.h>
#include <CANfetti.hpp>
CANfettiManager canManager;
void setup() {
Serial.begin(115200);
// Initialize CAN at 500 kbps
if (canManager.init(500000)) {
Serial.println("CAN initialized successfully!");
} else {
Serial.println("Failed to initialize CAN.");
}
}
void loop() {
// ...
}
#include <Arduino.h>
#include <CANfetti.hpp>
CANfettiManager canManager;
void setup() {
Serial.begin(115200);
canManager.init(500000);
}
void loop() {
// Build a simple CAN message with ID 0x123 and 3 bytes of data
CANfettiFrame frame = CANfetti()
.setId(0x123)
.setDataLength(3)
.setData((const uint8_t*)"\x01\x02\x03", 3)
.build();
bool success = canManager.sendMessage(frame);
Serial.println(success ? "Message sent!" : "Message failed!");
delay(1000);
}
#include <Arduino.h>
#include <CANfetti.hpp>
CANfettiManager canManager;
CANfettiFrame incomingFrame;
void setup() {
Serial.begin(115200);
canManager.init(500000);
}
void loop() {
// Non-blocking check for a new CAN message
if (canManager.receiveMessage(incomingFrame)) {
Serial.print("Received CAN ID: 0x");
Serial.println(incomingFrame.id, HEX);
Serial.print("Data Length: ");
Serial.println(incomingFrame.len);
Serial.print("Data Bytes: ");
for (int i = 0; i < incomingFrame.len; i++) {
Serial.print(incomingFrame.buf[i], HEX);
Serial.print(" ");
}
Serial.println();
}
// Continue with other tasks...
delay(10);
}
#include <Arduino.h>
#include <CANfetti.hpp>
CANfettiManager canManager;
void setup() {
Serial.begin(115200);
canManager.init(500000);
}
void loop() {
// Build an extended CAN message with ID 0x1ABCDE
CANfettiFrame frame = CANfetti()
.setId(0x1ABCDE)
.setExtendedFrame(true)
.setDataLength(4)
.setData((const uint8_t*)"\xAA\xBB\xCC\xDD", 4)
.build();
canManager.sendMessage(frame);
delay(1000);
}
#include <Arduino.h>
#include <CANfetti.hpp>
CANfettiManager canManager;
void setup() {
Serial.begin(115200);
if (canManager.init(500000)) {
Serial.println("CAN running...");
}
}
void loop() {
// Stop CAN after 5 seconds
if (millis() > 5000 && canManager.isRunning()) {
canManager.stop();
Serial.println("CAN has been stopped.");
}
}
-
Message Not Sending
- Ensure your transceiver wiring is correct and that the bus has proper termination (120Ω resistor on each end).
- Check that the bit rate matches all other devices on the CAN bus.
-
Platform Unrecognized
- This library requires Teensy 4.x or ESP32. If you're on an unsupported board, compilation will fail with an error.
-
Timeout or No Messages Received
- Confirm that another CAN node is actively sending data and that your wiring is correct.
- On ESP32, verify the TX/RX pin assignments (
GPIO_NUM_9
/GPIO_NUM_10
by default in the library, update as needed).
This library is distributed under the MIT License. See the LICENSE file for details.