Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
dfad85a
SDO Sample
DiegoLHendrix Nov 1, 2024
35424c8
This SDO no worky
DiegoLHendrix Nov 5, 2024
dd1dd90
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Nov 9, 2024
c00d790
idk anymore
DiegoLHendrix Nov 9, 2024
fbeb922
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Nov 12, 2024
4451a8b
The voices are getting louder
DiegoLHendrix Nov 18, 2024
ae64dc7
I Start Drinking On mondays at 8:15 am
DiegoLHendrix Nov 22, 2024
028f030
Start Drinking On comapny time
DiegoLHendrix Nov 23, 2024
9169c95
Good heavens I have arrived!
DiegoLHendrix Dec 3, 2024
4c750e4
Added comments
DiegoLHendrix Dec 3, 2024
580dbfa
CANopen is my sleep paralysis demon
DiegoLHendrix Dec 6, 2024
fff86b4
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Dec 6, 2024
ffc8495
please work cmake
DiegoLHendrix Dec 6, 2024
f85675a
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Dec 8, 2024
6319675
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Dec 14, 2024
9301881
Beetlejuice Beetlejuice Beetlejuice
DiegoLHendrix Dec 16, 2024
8a9b880
I am the Oppenheimer of CAN
DiegoLHendrix Dec 17, 2024
53d5b88
Merge branch 'feature/diegolhendrix/sdo-sample' of https://github.com…
DiegoLHendrix Dec 17, 2024
ff17043
Applied Formatting Changes During GitHub Build
Dec 17, 2024
359df66
Get me out of PR review hell
DiegoLHendrix Dec 21, 2024
0563097
Applied Formatting Changes During GitHub Build
Dec 21, 2024
7ee46da
I am Tyler Durden
DiegoLHendrix Jan 3, 2025
92d8cc7
Applied Formatting Changes During GitHub Build
Jan 3, 2025
df47e01
Merge branch 'main' of https://github.com/RIT-EVT/EVT-core into featu…
DiegoLHendrix Mar 18, 2025
a651e26
Made a macro and changed registerCallBack
DiegoLHendrix Mar 18, 2025
f4aca03
Applied Formatting Changes During GitHub Build
Mar 18, 2025
83b893b
Increased size of message size in snprintf
DiegoLHendrix May 2, 2025
0c37b58
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix May 24, 2025
d4f9389
Started pr changes
DiegoLHendrix Jun 7, 2025
04e4cfd
Added #ifdef to sdo canInterupt
DiegoLHendrix Jun 7, 2025
ff7c199
Deleted unnecessary comments
DiegoLHendrix Jun 12, 2025
ad442dc
Applied Formatting Changes During GitHub Build
Jun 14, 2025
221c07c
Edited more comments
DiegoLHendrix Jun 18, 2025
ea7e8b2
Fixed SDO_CONFIGURATION_1200 method in SDOCanNode.hpp
DiegoLHendrix Jul 28, 2025
3587bce
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Feb 14, 2026
59806c1
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Feb 16, 2026
9cf8008
Merge branch 'feature/diegolhendrix/sdo-sample' of https://github.com…
DiegoLHendrix Feb 16, 2026
d0dc51b
Fixed SDO methods
DiegoLHendrix Mar 14, 2026
5c1b840
Merge branch 'main' into feature/diegolhendrix/sdo-sample
DiegoLHendrix Mar 17, 2026
9532b47
Fixed UART in tpdo and rpdo after a merging error
DiegoLHendrix Mar 17, 2026
0a003be
Applied Formatting Changes During GitHub Build
Mar 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/core/io/CANOpenMacros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@
}, \
{ \
/* SDO Server Request COBID */ \
.Key = CO_KEY(0x1200, 0x01, CO_OBJ__N__R_), \
.Key = CO_KEY(0x1200, 0x01, CO_OBJ_DN__R_), \
.Type = CO_TUNSIGNED32, \
.Data = (CO_DATA) CO_COBID_SDO_REQUEST(), \
}, \
{ /* SDO Server Response COBID */ \
.Key = CO_KEY(0x1200, 0x02, CO_OBJ__N__R_), \
.Key = CO_KEY(0x1200, 0x02, CO_OBJ_DN__R_), \
.Type = CO_TUNSIGNED32, \
.Data = (CO_DATA) CO_COBID_SDO_RESPONSE(), \
}
Expand Down
35 changes: 35 additions & 0 deletions include/core/io/CANopen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
#include <core/io/CAN.hpp>
#include <core/io/types/CANMessage.hpp>
#include <core/utils/types/FixedQueue.hpp>
#include <core/utils/log.hpp>

// Allows for resizable CANOpen queue if needed
#ifndef CANOPEN_QUEUE_SIZE
#define CANOPEN_QUEUE_SIZE 150
#endif
namespace log = core::log;

namespace core::io {

Expand Down Expand Up @@ -94,6 +96,39 @@ void initializeCANopenNode(CO_NODE* canNode, CANDevice* canDevice, CO_IF_DRV* ca
*/
void processCANopenNode(CO_NODE* canNode);

/**
* Update Object Dictionary entry
*
* @param node[in] The SDO node
* @param sampleDataArray[in] The value to set sample data to
*/
CO_ERR SDOTransfer(CO_NODE &node, uint8_t *data, uint8_t size, uint32_t entry);

/**
* Read Object Dictionary entry
*
* @param node[in] The SDO node
* @param sampleDataArray[in] The value to set sample data to
*/
CO_ERR SDOReceive(CO_NODE &node, uint8_t *data, uint8_t size, uint32_t entry);

/**
* The application-specific callback function for finalizing an SDO transfer operation.
* @param csdo[in] is the client-SDO object.
* @param index[in] is the object dictionary index.
* @param sub[in] is the object dictionary subindex.
* @param code[in] indicates the completion status of the operation (0 for success, error code otherwise).
*/
void AppCSdoTransferCb(CO_CSDO *csdo, uint16_t index, uint8_t sub, uint32_t code);

/**
* The application-specific callback function for finalizing an SDO receive operation.
* @param csdo[in] is the client-SDO object.
* @param index[in] is the object dictionary index.
* @param sub[in] is the object dictionary subindex.
* @param code[in] indicates the completion status of the operation (0 for success, error code otherwise).
*/
void AppCSdoReceiveCb(CO_CSDO *csdo, uint16_t index, uint8_t sub, uint32_t code);
} // namespace core::io

#endif
1 change: 1 addition & 0 deletions samples/canopen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
add_subdirectory(canopen_rpdo)
add_subdirectory(canopen_sample)
add_subdirectory(canopen_sdo)
add_subdirectory(canopen_tpdo)
12 changes: 7 additions & 5 deletions samples/canopen/canopen_rpdo/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <core/manager.hpp>
#include <core/utils/time.hpp>
#include <core/utils/types/FixedQueue.hpp>
#include <core/utils/log.hpp>

#include <core/io/CANopen.hpp>

Expand All @@ -19,6 +20,7 @@
namespace io = core::io;
namespace dev = core::dev;
namespace time = core::time;
namespace log = core::log;

///////////////////////////////////////////////////////////////////////////////
// EVT-core CAN callback and CAN setup. This will include logic to set
Expand All @@ -36,20 +38,18 @@ namespace time = core::time;
* @param message[in] The passed in CAN message that was read.
*/

io::UART& uart = io::getUART<io::Pin::UART_TX, io::Pin::UART_RX>(9600);

// create a can interrupt handler
void canInterrupt(io::CANMessage& message, void* priv) {
auto* queue = (core::types::FixedQueue<CANOPEN_QUEUE_SIZE, io::CANMessage>*) priv;

// print out raw received data
uart.printf("Got RAW message from %X of length %d with data: ", message.getId(), message.getDataLength());
log::LOGGER.log(log::Logger::LogLevel::INFO, "Got RAW message from %X of length %d with data: ", message.getId(), message.getDataLength());
uint8_t* data = message.getPayload();
for (int i = 0; i < message.getDataLength(); i++) {
uart.printf("%X ", *data);
log::LOGGER.log(log::Logger::LogLevel::INFO, "%X ", *data);
data++;
}
uart.printf("\r\n");
log::LOGGER.log(log::Logger::LogLevel::INFO, "\r\n");

if (queue != nullptr)
queue->append(message);
Expand All @@ -59,6 +59,8 @@ int main() {
// Initialize system
core::platform::init();

io::UART& uart = io::getUART<io::Pin::UART_TX, io::Pin::UART_RX>(9600);

// Initialize the timer
dev::Timer& timer = dev::getTimer<dev::MCUTimer::Timer2>(100);

Expand Down
4 changes: 4 additions & 0 deletions samples/canopen/canopen_sdo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include(../../../cmake/evt-core_build.cmake)

set( SAMPLE_SOURCES main.cpp SDOCanNode.cpp)
make_exe(canopen_sdo "${SAMPLE_SOURCES}")
72 changes: 72 additions & 0 deletions samples/canopen/canopen_sdo/SDOCanNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "SDOCanNode.hpp"

SDOCanNode::SDOCanNode() {
sampleDataA = 6;
sampleDataB = 0;
}

void SDOCanNode::SDO_Transfer(CO_NODE &node) {
/* Increment the first element of sampleDataArray by 1. */
sampleDataArray[0]++;
/* Set the second element of sampleDataArray to twice the new value of the first element. */
sampleDataArray[1] = sampleDataArray[0] * 2;

/* Initiate an SDO transfer using the specified node and sampleDataArray,
* targeting object dictionary entry 0x2100:02. */
CO_ERR err = core::io::SDOTransfer(node, sampleDataArray, 2, CO_DEV(0x2100,0x02));

/* Check if the SDO transfer was successfully started. */
if (err == CO_ERR_NONE) {
/* Transfer is started successfully */
log::LOGGER.log(log::Logger::LogLevel::INFO, "SDOTransfer Sent Request");

/* Note: don't use the 'readValue' until transfer is finished! */
} else {
/* Unable to start the SDO transfer */
log::LOGGER.log(log::Logger::LogLevel::ERROR, "SDOTransfer Request Error");
}
}

void SDOCanNode::SDO_Receive(CO_NODE &node) {
/* Initiate an SDO receive operation, reading data into sampleDataArray
* from object dictionary entry 0x2100:01. */
CO_ERR err = core::io::SDOReceive(node, sampleDataArray, 1, CO_DEV(0x2100,0x01));

/* Check if the SDO receive operation was successfully started. */
if (err == CO_ERR_NONE) {
/* Transfer is started successfully */
log::LOGGER.log(log::Logger::LogLevel::INFO, "SDOReceive Sent Request");

/* Note: don't use the 'readValue' until transfer is finished! */
} else {
/* Unable to start the SDO transfer */
log::LOGGER.log(log::Logger::LogLevel::ERROR, "SDOReceive Request Error");
}
}

uint8_t SDOCanNode::getSampleDataA() {
return sampleDataA;
}

uint16_t SDOCanNode::getSampleDataB() {
return sampleDataB;
}

void SDOCanNode::update() {
sampleDataA++;
if (sampleDataA % 20 == 0) {
sampleDataB *= 3;
}
}

CO_OBJ_T* SDOCanNode::getObjectDictionary() {
return &objectDictionary[0];
}

uint8_t SDOCanNode::getNumElements() {
return OBJECT_DICTIONARY_SIZE;
}

uint8_t SDOCanNode::getNodeID() {
return NODE_ID;
}
141 changes: 141 additions & 0 deletions samples/canopen/canopen_sdo/SDOCanNode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#include <cstdint>
#include <core/utils/log.hpp>

#include <co_core.h>
#include <co_csdo.h>
#include <core/io/CANDevice.hpp>
#include <core/io/CANOpenMacros.hpp>
#include <core/io/CANOpen.hpp>

/**
* Representation of the CAN node. Handles constructing the object
* dictionary and other baseline settings. The idea is that each "board"
* will have a specific object dictionary associated with it. The object
* dictionary itself will also need to have information on "data of interest".
* For example, a temperature management system may to expose water pump
* flow rate in the object dictionary.
*/

namespace log = core::log;

class SDOCanNode : public CANDevice {
public:
SDOCanNode();

/**
* Update Object Dictionary entry
*
* @param node[in] The canopen node to write to
*/
void SDO_Transfer(CO_NODE &node);

/**
* Read Object Dictionary entry
*
* @param node[in] The canopen node to read from
*/
void SDO_Receive(CO_NODE &node);

/**
* Get the contained sample data
*
* @return The value of the sample data
*/
uint8_t getSampleDataA();
uint16_t getSampleDataB();

/**
* increments counters up
*/
void update();

/**
* Get a pointer to the start of the object dictionary
*
* @return Pointer to the start of the object dictionary
*/
CO_OBJ_T* getObjectDictionary() override;

/**
* Get the number of elements in the object dictionary.
*
* @return The number of elements in the object dictionary
*/
uint8_t getNumElements() override;

/**
* Get the device's node ID
*
* @return The node ID of the can device.
*/
uint8_t getNodeID() override;

/**
* Get the device's node ID
*
* @return The node ID of the can device.
*/
static constexpr uint8_t NODE_ID = 2;

private:
/**
* This sample data will be exposed over CAN through the object
* dictionary. The address of the variable will be included in the
* object dictionary and can be updated via SDO via a CANopen client.
* This device will then broadcast the value via a triggered PDO.
*/
uint8_t sampleDataA;
uint16_t sampleDataB;
Comment on lines +73 to +74
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are not really using these values in your sample, are you able to use them for your transfer and receive somehow instead of a raw array?

uint8_t sampleDataArray[2] = {0, 0};

/**
* Have to know the size of the object dictionary for initialization
* process.
*/
static constexpr uint8_t OBJECT_DICTIONARY_SIZE = 24;

/**
* The object dictionary itself. Will be populated by this object during
* construction.
*
* The plus one is for the special "end of dictionary" marker.
*/
CO_OBJ_T objectDictionary[OBJECT_DICTIONARY_SIZE + 1] = {
MANDATORY_IDENTIFICATION_ENTRIES_1000_1014,
HEARTBEAT_PRODUCER_1017(2000),
IDENTITY_OBJECT_1018,
SDO_CONFIGURATION_1200,

{
/* Communication Object SDO Server */
.Key = CO_KEY(0x1280, 0x00, CO_OBJ_D___R_),
.Type = CO_TUNSIGNED32,
.Data = (CO_DATA) 0x03,
},
{
/* SDO Server Request COBID */
.Key = CO_KEY(0x1280, 0x01, CO_OBJ_D___R_),
.Type = CO_TUNSIGNED32,
.Data = (CO_DATA) CO_COBID_SDO_REQUEST(),
},
{ /* SDO Server Response COBID */
.Key = CO_KEY(0x1280, 0x02, CO_OBJ_D___R_),
.Type = CO_TUNSIGNED32,
.Data = (CO_DATA) CO_COBID_SDO_RESPONSE(),
},
{
.Key = CO_KEY(0x1280, 0x03, CO_OBJ_D___R_),
.Type = CO_TUNSIGNED8,
.Data = (CO_DATA) 1,
},

// User defined data, this will be where we put elements that can be
// accessed via SDO and depending on configuration PDO
DATA_LINK_START_KEY_21XX(0, 0x02),
DATA_LINK_21XX(0x00, 0x01, CO_TUNSIGNED8, &sampleDataA),
DATA_LINK_21XX(0x00, 0x02, CO_TUNSIGNED16, &sampleDataB),
Comment on lines +100 to +104
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you using these entries?


// End of dictionary marker
CO_OBJ_DICT_ENDMARK,
};
};
Loading