This is the UCLA Bruin Racing SMV CAN Bus communication library for the ESP32, Teensy 4, and RP2040 CAN. This guide DOES NOT cover wiring guides. This library can be found in the Arduino library manager* by simply searching "UCLA".
For this library we are using 3 different microcontrollers
- ESP32
- The DAQ Specific board for uploading data to the cloud
- Teensy 4
- Legacy code from the 2022-2023 year (see commit:
a04540d9ed8a43bf7a0ba898fdd3b3a5d62bfa2f)
- Legacy code from the 2022-2023 year (see commit:
- RP2040 CAN
- The newest edition of microcontrollers
Note that: EACH controller has their own specific implementation so follow the appropriate section of the guide depending on your hardware.
For the Teensy 4, we will be using the FlexCAN_T4 library
We rely on the FlexCAN_T4 library that should already be included when you set up Arduino IDE with the Teensy boards, but if you don't have it installed you can find it here:
If you don't have the FlexCAN_T4 library, you must install it by adding it into your library folder.
Go to https://github.com/tonton81/FlexCAN_T4 or click here and clone the repository into Arduino IDE's library folder (see Note 1 for help)
You must also install this current library into the libraries folder.
For the Adafruit RP2040 CAN Bus Feather MCP2515.
Following the Adafruit guide found here, you need to install the Adafruit MCP2515 library from the library manager that is built-in to Arduino IDE.
Afterwards you must install this library by cloning it into Arduino IDE's library folder (see Note 1 for help)
This is mainly for DAQ team members to develop since this is a one off board for the car. See the examples folder for actual implementation
To include the library in your sketch you can add the following line:
include "SMVcanbus.h"
To begin using the CAN Bus, you must initialize a canbus object
CANBUS can(device_id);
You can replace device_id with the enum name of your device from the address book, for example: CANBUS can(Bear_1);
Let's take a look at one of the example sketches
#include "SMVcanbus.h"
CANBUS can(Bear_1);
double data = 1.5;
void setup(void){
Serial.begin(115200);
can.begin(); //YOU ONLY NEED THIS LINE FOR RP2040
delay(400); //for printing
}
void loop(){
can.send(data, RPM);
delay(500); //be aware of how fast you send as not to overwhelm the system
data += 1.5;
Serial.println("sent packet!");
}
-
First we are including the library
#include "SMVcanbus.h -
Then we initialize the CANBUS object with device id of the bear
CANBUS can(Bear_1); -
OBSERVE that the
can.begin();line is ONLY necessary if you are using an RP2040, you may omit this line if you are using a Teensy 4.
The send function has a function signature of send(double data, int dataType);
- In the example we are passing in the arbitrary data variable and the data type
RPMwhich is also taken from the address book.
And that's it! You just send data over CAN
Let's take a look at one of the receiving examples
#include "SMVcanbus.h"
CANBUS can(Bear_1);
void setup(void){
Serial.begin(115200);
can.begin(); //THIS IS FOR RP2040 ONLY, OMIT OTHERWISE
}
void loop(){
can.looper();
if(can.isThere())
{
Serial.print("The data is: ");
Serial.println(can.getData());
Serial.print("The Hardware Type is: ");
Serial.println(can.getHardware());
Serial.print("The Data Type is: ");
Serial.println(can.getDataType());
}
delay(20);
}
-
First we are including the library
#include "SMVcanbus.h -
Then we initialize the CANBUS object with device id of the bear
CANBUS can(Bear_1); -
From there in the
loop()function we insertcan.looper();- This MUST BE INCLUDED inside of the loop function if you want to receive data.
-
Afterwards in an
ifstatement we are checkingcan.isThere()- This function returns True if a NEW message was received after the previous call of
getData();
- This function returns True if a NEW message was received after the previous call of
-
After checking if we have a new message we can get the contents of the message
can.getData();returns a double representing the payload of the packet.can.getHardware();returns a const char* (if RP2040) or a string (if Teensy 4) that represents the device that sent the packet.can.getDataType();returns a const char* (if RP2040) or a string (if Teensy 4) that represents the data type of the device that sent the packet.- NOTE that you can still call these data accessing functions without calling
isThere(). It will just return the data from the last received packet.- you accept the fact that you might be looking at old data multiple times if you don't check for new messages with
can.isThere();
- you accept the fact that you might be looking at old data multiple times if you don't check for new messages with
And that's it for receiving data!
Windows: For windows, the library folder is usually found here:
C:\Users\{username}\Documents\Arduino
Mac OS: For Macs it's usually found here:
/Users/{username}/Documents/Arduino
Linux: If you're on linux, I don't think I need to write it here but:
/home/{username}/Arduino
This function is only necessary for the RP2040 version ONLY it will not compile if you try it with the Teensy version.
enum devices {
Bear_1,
UI,
HS1,
HS2,
HS3,
HS4,
FC,
Joule_H,
Joule_L,
Safety,
DAQ_Board
};
enum motorMessage {
Hall_velocity,
Torque_motor,
Current,
Board_Temp,
Motor_Temp,
};
enum UIMessage {
Blink_Left,
Blink_Right,
Reverse,
Headlights,
Wipers,
Hazard,
Button,
Switch,
Motor,
Horn,
DAQ_Button
};
enum HSMessage {
Gyro_x,
Gyro_y,
Gyro_z,
Accel_x,
Accel_y,
Accel_z,
Pressure,
Torque_HS
};
enum FCMessage {
Gas,
Brake
};
enum JouleMessage {
Power
};
enum DAQMessage {
Longitude,
Latitude,
Speed
};