Skip to content

Commit 2f7ae56

Browse files
committed
Merge remote-tracking branch 'origin/main' into nixfmt
2 parents 811bd18 + 9578870 commit 2f7ae56

17 files changed

Lines changed: 110 additions & 601 deletions

README.md

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# rover-Embedded-Lib
1+
# astra-embedded-lib
22

33
Standardizing ASTRA's embedded code.
44

@@ -20,7 +20,6 @@ team-wide constants, just to name a few. Here are a few examples:
2020
* `parseInput(const String, std::vector<String>&)`: takes input from USB or UART and separates it into the vector, using commas as delimiters. Very useful for dealing with commands and data input from other mcu's.
2121
* `CAN_sendDutyCycle(uint8_t, AstraCAN&)`: Formats and sends a CAN packet to a REV motor controller with a duty cycle. All communication with REV motor controllers should reside in `AstraREVCAN.{h,cpp}`.
2222
* `isCalibrated(Adafruit_BNO055&)`: Attempts to check whether the BNO has been calibrated in EEPROM.
23-
* `COMMS_UART`: Macro for the UART interface used by each MCU.
2423
* `SERIAL_BAUD`: Standard baudrate for USB Serial used by all of ASTRA's mcu's.
2524

2625
## Usage in PlatformIO
@@ -29,16 +28,16 @@ team-wide constants, just to name a few. Here are a few examples:
2928

3029
1. Add the following line to `lib_deps` in your `/platformio.ini`:
3130

32-
**https://github.com/SHC-ASTRA/rover-Embedded-Lib**
31+
**https://github.com/SHC-ASTRA/astra-embedded-lib**
3332

34-
2. Add the include statement for your project. E.g., `#include "project/CITADEL.h"`
35-
3. Make sure to grab the correct dependencies for `/platformio.ini` from the project headers.
33+
2. Add the dependencies you need from `include/`. E.g., `#include "AstraVicCAN.h"`
34+
3. Make sure to grab the correct dependencies for `/platformio.ini` from the library headers.
3635

3736
### Starting a new PlatformIO project
3837

39-
1. Copy the example file from `/.pio/libdeps/[board]/rover-Embedded-Lib/examples/Template/`
40-
2. Grab the correct project header from `include/project/` or create one
41-
from `TEMPLATE.h`
38+
1. Copy the example file from `/.pio/libdeps/[board]/astra-Embedded-Lib/examples/Template/`
39+
2. Grab whatever headers you need from `include/`
40+
3. Get writing!
4241

4342
### Updating your libraries
4443

@@ -55,12 +54,10 @@ PlatformIO provides a button which will check for updates in all of your depende
5554

5655
* **Library files** - Depending on context, either the files generally contained in the library,
5756
or the main functional C++ files containing functions and classes.
58-
* **Project header** - A header file that corresponds to one PlatformIO project, residing in `include/project/`.
5957

6058
### File names
6159

6260
* **Library files** - Camel case with the first letter of all words, including the first, capitalized. Ex: `AstraArm.cpp`
63-
* **Project headers** - All caps. Ex: `CITADEL.h`
6461

6562
## Files
6663

@@ -69,6 +66,7 @@ or the main functional C++ files containing functions and classes.
6966
* `AstraArm.h/.cpp` - Arm
7067
* `AstraMotors.h/.cpp` - REV motor
7168
* `AstraNP.h/.cpp` - Status indicator using NeoPixel
69+
* `AstraVicCAN.h` - Serial/CAN-analogous communication standard
7270

7371
### Library
7472

@@ -81,17 +79,6 @@ or the main functional C++ files containing functions and classes.
8179
* `AstraSensors.h/.cpp` - functions for sensors
8280
* `AstraMisc.h/.cpp` - functions, consts, etc. useful to all ASTRA projects.
8381

84-
### Project Headers
85-
86-
* One per project.
87-
* All caps file name, aside from `.h`
88-
* Found in `include/project/`
89-
* Includes pinouts (all pinouts important for code, optionally ones not needed for code)
90-
* Includes constants relating to hardware
91-
* DOES NOT include constants only relevant to the code
92-
* The goal is too put less work on the embedded programmer, abstracting away electronics
93-
* The embedded programmer SHOULD NOT have to edit their project's library. When in doubt, it goes in `main.cpp`.
94-
9582
## Theory
9683

9784
* `main.cpp` includes all the library headers it needs
@@ -100,19 +87,6 @@ included in `main.cpp`, then no include errors, but if it is, then you will get
10087
* `.cpp` files enable themselves when all of its required external libraries are found. External libraries
10188
are 90% of the reason the `.cpp` files need the option to be disabled.
10289

103-
## Updating this Repository
104-
105-
When making any update to this repository, before updating `main`, make sure to increment the version number in `library.json`, line 3.
106-
Without making this change, projects using this library will not update automatically. Instead, they will have to delete the library
107-
locally and let PlatformIO re-download it. (Not sure if this is true.......)
108-
109-
When making commits, it would be amazing if you use [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/#summary).
110-
111-
### Creating a new project header
112-
113-
1. Copy `TEMPLATE.h` in `rover-Embedded-Lib/include/project/`.
114-
2. Choose a project macro and add it to `ASTRA.h`.
115-
11690
### Creating a new header file
11791

11892
1. Place the header file in `include/` and its implementation `.cpp` in `src/`.

include/AstraCAN.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,9 @@ void printCANframe(CanFrame& frame);
4141

4242
# include <FlexCAN_T4.h> // https://github.com/tonton81/FlexCAN_T4
4343

44-
// Core and FAERIE use CAN1, Arm uses CAN3
45-
# ifdef ARM
46-
typedef FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> AstraCAN;
47-
# else
44+
// NOTE: you may need to change the CAN bus number (e.g., CAN1 -> CAN3) depending on
45+
// which pins you are using for your CAN transceiver.
4846
typedef FlexCAN_T4<CAN1, RX_SIZE_256, TX_SIZE_16> AstraCAN;
49-
# endif
5047

5148

5249
# endif // End microcontroller check

include/AstraMotors.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ class AstraMotors {
120120
// Controlling physical motor
121121
//---------------------------------------------//
122122

123+
void setSlowStatusPeriods(); // Set status frame periods to 100 ms for motor on main
124+
123125
// Send the identify command to the SparkMax; makes it flash its LED purple and white
124126
inline void identify() {
125127
CAN_identifySparkMax(motorID);

include/AstraREVCAN.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,25 @@ void CAN_setParameter(uint8_t deviceId, sparkMax_ConfigParameter parameterID, sp
6969
*/
7070
void CAN_reqParameter(uint8_t deviceId, sparkMax_ConfigParameter parameterID);
7171

72+
/**
73+
* @brief Set the period of a periodic status frame on the specified SparkMax device
74+
*
75+
* These are the default periods, in ms:
76+
* Status0 - 10
77+
* Status1 - 20
78+
* Status2 - 20
79+
* Status3 - 50
80+
* Status4 - 20
81+
* Status5 - 200
82+
* Status6 - 200
83+
* Status7 - 250
84+
*
85+
* @param deviceId REV ID
86+
* @param frameId The ID of the periodic status frame to set the period of
87+
* @param periodMs The period to set for the specified periodic status frame, in milliseconds
88+
*/
89+
void CAN_setStatusPeriod(uint8_t deviceId, sparkMax_PeriodicFrame frameId, int periodMs);
90+
7291

7392
//-------------------------------------//
7493
// Backwards Compatibility Functions //

include/AstraREVTypes.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <Arduino.h>
99

1010

11+
// https://docs.revrobotics.com/brushless/spark-max/operating-modes#brake-coast-mode-idle-behavior
1112
enum class sparkMax_IdleMode {
1213
kCoast = 0,
1314
kBrake = 1
@@ -43,6 +44,21 @@ enum class sparkMax_ctrlType {
4344
kSmartMotion = 0x52
4445
};
4546

47+
// https://docs.revrobotics.com/brushless/spark-max/control-interfaces#periodic-status-frames
48+
enum class sparkMax_PeriodicFrame {
49+
kStatus0 = 0,
50+
kStatus1 = 1,
51+
kStatus2 = 2,
52+
kStatus3 = 3,
53+
kStatus4 = 4,
54+
kStatus5 = 5,
55+
kStatus6 = 6,
56+
kStatus7 = 7
57+
};
58+
59+
constexpr int sparkMax_statusFrame_baseId =
60+
0x60; // Base ID for status frames; actual ID is base + frame number
61+
4662
struct motorStatus0 {
4763
double appliedOutput;
4864
uint16_t faults;
@@ -81,6 +97,7 @@ enum class sparkMax_ParameterType : uint8_t {
8197
kBool = 0x3,
8298
};
8399

100+
// https://docs.revrobotics.com/brushless/spark-max/parameters
84101
enum class sparkMax_ConfigParameter : int32_t {
85102
kCanID = 0x0,
86103
kInputMode = 0x1,

include/AstraVicCAN.h

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ using namespace unilib;
4343
# define SUBMODULE_CAN_ID CanMcuId::MCU_ARM
4444
#elif defined(DIGIT)
4545
# define SUBMODULE_CAN_ID CanMcuId::MCU_DIGIT
46-
#elif defined(FAERIE)
47-
# define SUBMODULE_CAN_ID CanMcuId::MCU_FAERIE
46+
#elif defined(LANCE)
47+
# define SUBMODULE_CAN_ID CanMcuId::MCU_LANCE
4848
#elif defined(CITADEL)
4949
# define SUBMODULE_CAN_ID CanMcuId::MCU_CITADEL
5050
#else // Default - no macro in platformio.ini; will only respond to broadcast messages
@@ -74,8 +74,8 @@ bool mcuIdFromString(String str, CanMcuId* mcuID) {
7474
*mcuID = CanMcuId::MCU_ARM;
7575
else if (str == "digit")
7676
*mcuID = CanMcuId::MCU_DIGIT;
77-
else if (str == "faerie")
78-
*mcuID = CanMcuId::MCU_FAERIE;
77+
else if (str == "lance")
78+
*mcuID = CanMcuId::MCU_LANCE;
7979
else if (str == "citadel")
8080
*mcuID = CanMcuId::MCU_CITADEL;
8181
else
@@ -99,8 +99,8 @@ String mcuIdToString(const CanMcuId mcuID) {
9999
return "arm";
100100
else if (mcuID == CanMcuId::MCU_DIGIT)
101101
return "digit";
102-
else if (mcuID == CanMcuId::MCU_FAERIE)
103-
return "faerie";
102+
else if (mcuID == CanMcuId::MCU_LANCE)
103+
return "lance";
104104
else if (mcuID == CanMcuId::MCU_CITADEL)
105105
return "citadel";
106106
else // Should never run unless an MCU is added and not included in this function
@@ -264,12 +264,13 @@ class VicCanFrame {
264264
* @return true if a frame is successfully read;
265265
* @return false if no frame is received.
266266
*/
267-
bool readCan() {
267+
bool readCan(CanFrame* rawFrame) {
268268
static CanFrame inFrame;
269269
if (!ESP32Can.readFrame(inFrame, 0))
270270
return false; // No CAN frame received
271271

272272
parseCanFrame(inFrame);
273+
*rawFrame = inFrame;
273274
return true;
274275
}
275276
#endif
@@ -356,10 +357,29 @@ class VicCanController {
356357
* @brief Extends readCanFrame() to check destination of CAN Frame, relays stray CAN frames
357358
* to Serial if relayMode is on, and checks for a queued frame from relayFromSerial().
358359
*
360+
* (Non-REVCAN compatible variant)
361+
*
362+
* @return true upon reading a CAN frame for this MCU;
363+
* @return false upon not finding a CAN frame or only reading one for a different MCU
364+
*/
365+
inline bool readCan() {
366+
bool isREV;
367+
CanFrame rawFrame;
368+
return readCan(&isREV, &rawFrame);
369+
}
370+
371+
/**
372+
* @brief Extends readCanFrame() to check destination of CAN Frame, relays stray CAN frames
373+
* to Serial if relayMode is on, and checks for a queued frame from relayFromSerial().
374+
*
375+
* @param isREV [out] whether the frame read is a REV CAN frame
376+
* @param outFrame [out] the raw CAN frame read, for use with REV CAN frames that need to be parsed by
377+
* loop()
378+
*
359379
* @return true upon reading a CAN frame for this MCU;
360380
* @return false upon not finding a CAN frame or only reading one for a different MCU
361381
*/
362-
bool readCan() {
382+
bool readCan(bool* isREV, CanFrame* outFrame) {
363383
// Check for queued frame from relayFromSerial()
364384
if (relayFrameWaiting) {
365385
relayFrameWaiting = false;
@@ -369,7 +389,7 @@ class VicCanController {
369389
return true; // Use inVicCanFrame already set by relayFromSerial()
370390
}
371391

372-
#ifdef CAN_AVAILABLE
392+
// #ifdef CAN_AVAILABLE
373393
// Run through up to 5 messages on the CAN network.
374394
// If one is found to act on, break and return true.
375395
// If a read fails, there are no more messages to read; return false.
@@ -380,31 +400,38 @@ class VicCanController {
380400
int count = 0;
381401
while (count++, count < 5) {
382402
// Check CAN network for a frame
383-
if (!inVicCanFrame.readCan())
403+
if (!inVicCanFrame.readCan(outFrame)) {
404+
*isREV = false;
384405
return false; // No CAN frame received
406+
}
385407

386-
# ifdef VICCAN_DEBUG
408+
#ifdef VICCAN_DEBUG
387409
Serial.println("Received CAN frame: ");
388410
Serial.println(inVicCanFrame.toStr());
389-
# endif
411+
#endif
390412

391413
// Relay stray CAN frames to Serial if relayMode is on
392414
// Broadcast messages are specifically not relayed.
393-
if (!inVicCanFrame.isForMe()) {
415+
if (!outFrame->extd && !inVicCanFrame.isForMe()) {
394416
if (relayMode) {
395-
# ifdef VICCAN_DEBUG
417+
#ifdef VICCAN_DEBUG
396418
Serial.println("Relaying from CAN to Serial:");
397419
Serial.println(inVicCanFrame.toStr());
398-
# endif
420+
#endif
399421
relayToSerial(inVicCanFrame);
400422
}
401423
continue; // Not for us; try to process the next message
424+
} else if (outFrame->extd) {
425+
// REV CAN Frame; don't do anything, let loop() parse it with *outFrame
426+
*isREV = true;
427+
return false;
402428
}
403429

404430
// We have a CAN command that we should act on.
431+
*isREV = false;
405432
return true;
406433
}
407-
#endif
434+
// #endif
408435
return false;
409436
}
410437

0 commit comments

Comments
 (0)