Quickstart¶
Connect a host to a Vortex node, write the transport, and start the node in a CiA 402 mode in about 15 lines.
A started drive can move the motor
NmtCommand::Start puts the node in Operational, and the CiA 402 enable sequence powers the motor. Clamp the
rotor or remove the load until you have checked the node ID and the objects you write.
Wiring¶
| Host | Vortex V1 | Notes |
|---|---|---|
| CAN_H | CAN_H | Twisted pair with CAN_L |
| CAN_L | CAN_L | |
| GND | GND | A common reference for the transceivers |
| 120 Ω termination | 120 Ω termination | One at each end of the bus, none in between |
The bit rate must match on every node: 500 kbit/s is what the Vortex V1 HAL configures. See Hardware.
Add the driver¶
The transport¶
The driver calls one method of yours, send(). For a first test on a PC, record the frames instead of sending
them:
class LoopbackTransport final : public hf::vortex::VortexCanTransport {
public:
bool send(const hf::vortex::VortexCanFrame& frame) noexcept override {
if (count_ == kMaxFrames) {
return false; // full: report a TX failure
}
frames_[count_++] = frame;
return true;
}
std::size_t count() const noexcept { return count_; }
const hf::vortex::VortexCanFrame& frame(std::size_t i) const noexcept { return frames_[i]; }
private:
static constexpr std::size_t kMaxFrames = 16;
hf::vortex::VortexCanFrame frames_[kMaxFrames]{};
std::size_t count_ = 0;
};
On a board, wrap your CAN driver instead: Porting has a ten-line adapter over BaseCan.
Start a node¶
#include "vortex/VortexHostSession.hpp"
#include "vortex/VortexProtocol.hpp"
using namespace hf::vortex;
// Put node 5 in Operational and select CiA 402 profile velocity mode (3).
bool start_node_in_velocity_mode(VortexCanTransport& bus) {
VortexHostSession session(bus);
constexpr std::uint8_t kNode = 5;
if (!session.sendNmt(NmtCommand::Start, kNode)) { // 0x000: 01 05
return false; // transport refused the frame
}
return session.sdoDownloadExpedited(kNode, kIdxModesOfOperation, // 0x605: 2F 60 60 00 03
/*sub=*/0, /*value=*/3, /*size=*/1);
}
What each step does¶
| Step | Frame on the bus | Effect on the node |
|---|---|---|
VortexHostSession session(bus) |
none | Binds the session to your transport; no state, no allocation |
sendNmt(NmtCommand::Start, 5) |
ID 0x000, 2 bytes: 01 05 |
Node 5 enters Operational |
sdoDownloadExpedited(5, 0x6060, 0, 3, 1) |
ID 0x605, 8 bytes: 2F 60 60 00 03 00 00 00 |
Writes 3 (profile velocity) to modes of operation |
Both calls return true when your transport accepted the frame. They do not wait for the node: the SDO response
(0x585) is yours to read if you need the confirmation.
If it does not work¶
| Symptom | Check |
|---|---|
send() returns false |
The controller is bus-off or its TX queue is full: check termination, bit rate and that another node acknowledges |
| Frames leave, the node does nothing | Wrong node ID; the node is still booting (wait for its boot-up message 0x700 + node) |
SDO abort (0x580 + node, byte 0 0x80) |
The object does not exist or is read-only on that node; check its EDS |
| Nothing on the bus at all | Transceiver in standby (on Vortex V1 the standby line is on the PCAL95555 expander) |
Next: Hardware.