17Cia402State pc_cia402_state(uint16_t sw)
20 if ((sw & 0x4F) == 0x00)
22 return Cia402State::not_ready_to_switch_on;
24 if ((sw & 0x4F) == 0x40)
26 return Cia402State::switch_on_disabled;
28 if ((sw & 0x6F) == 0x21)
30 return Cia402State::ready_to_switch_on;
32 if ((sw & 0x6F) == 0x23)
34 return Cia402State::switched_on;
36 if ((sw & 0x6F) == 0x27)
38 return Cia402State::operation_enabled;
40 if ((sw & 0x6F) == 0x07)
42 return Cia402State::quick_stop_active;
44 if ((sw & 0x4F) == 0x0F)
46 return Cia402State::fault_reaction_active;
48 if ((sw & 0x4F) == 0x08)
50 return Cia402State::fault;
52 return Cia402State::unknown;
55uint16_t pc_cia402_controlword(Cia402Command cmd)
59 case Cia402Command::shutdown:
61 case Cia402Command::switch_on:
62 case Cia402Command::disable_operation:
64 case Cia402Command::enable_operation:
66 case Cia402Command::disable_voltage:
68 case Cia402Command::quick_stop:
70 case Cia402Command::fault_reset:
76uint16_t pc_cia402_enable_sequence(Cia402State state)
80 case Cia402State::fault:
81 case Cia402State::fault_reaction_active:
82 return pc_cia402_controlword(Cia402Command::fault_reset);
83 case Cia402State::switch_on_disabled:
84 return pc_cia402_controlword(Cia402Command::shutdown);
85 case Cia402State::ready_to_switch_on:
86 return pc_cia402_controlword(Cia402Command::switch_on);
87 case Cia402State::switched_on:
88 case Cia402State::quick_stop_active:
89 case Cia402State::operation_enabled:
90 return pc_cia402_controlword(Cia402Command::enable_operation);
92 return pc_cia402_controlword(Cia402Command::disable_voltage);
96bool pc_cia402_sdo_set_controlword(
CanFrame *out, uint8_t node, uint16_t controlword)
100 return pc_canopen_build_sdo_write(out, node, CIA402_OD_CONTROLWORD, 0, d, 2);
103bool pc_cia402_sdo_set_mode(
CanFrame *out, uint8_t node, Cia402Mode mode)
105 uint8_t d = (uint8_t)(int8_t)mode;
106 return pc_canopen_build_sdo_write(out, node, CIA402_OD_MODES_OF_OPERATION, 0, &d, 1);
109bool pc_cia402_sdo_set_target_position(
CanFrame *out, uint8_t node, int32_t position)
113 return pc_canopen_build_sdo_write(out, node, CIA402_OD_TARGET_POSITION, 0, d, 4);
116bool pc_cia402_sdo_set_target_velocity(
CanFrame *out, uint8_t node, int32_t velocity)
120 return pc_canopen_build_sdo_write(out, node, CIA402_OD_TARGET_VELOCITY, 0, d, 4);
123bool pc_cia402_sdo_set_target_torque(
CanFrame *out, uint8_t node, int16_t torque)
127 return pc_canopen_build_sdo_write(out, node, CIA402_OD_TARGET_TORQUE, 0, d, 2);
130bool pc_cia402_sdo_read(
CanFrame *out, uint8_t node, uint16_t index, uint8_t sub)
132 return pc_canopen_build_sdo_read(out, node, index, sub);
137static bool sdo_upload_bytes(
const CanFrame *f, uint16_t want_index, uint8_t need, uint8_t *out)
139 CanopenSdoResponse resp;
140 if (!pc_canopen_parse_sdo_response(f, &resp))
144 if (resp.is_abort || !resp.is_upload || !resp.expedited || resp.len < need)
148 if (want_index != 0 && resp.index != want_index)
152 memcpy(out, resp.data, need);
156bool pc_cia402_sdo_get_u16(
const CanFrame *f, uint16_t want_index, uint16_t *value)
159 if (!value || !sdo_upload_bytes(f, want_index, 2, d))
167bool pc_cia402_sdo_get_i32(
const CanFrame *f, uint16_t want_index, int32_t *value)
170 if (!value || !sdo_upload_bytes(f, want_index, 4, d))
178size_t pc_cia402_pack_command(uint8_t *buf,
size_t cap, uint16_t controlword, int32_t target)
185 p +=
pc_wr32le(buf + p, (uint32_t)target);
189bool pc_cia402_unpack_status(
const uint8_t *buf,
size_t len, uint16_t *statusword, int32_t *actual)
191 if (!buf || !statusword || !actual || len < 6)
CiA 402 / IEC 61800-7-201 drive + motion profile (PC_ENABLE_CIA402) over CANopen.
Fixed-width integer serializers into a raw uint8_t* buffer - one source of truth.
uint32_t pc_rd32le(const uint8_t *p)
Read a little-endian u32 at p.
size_t pc_wr32le(uint8_t *p, uint32_t v)
Write v little-endian at p.
uint16_t pc_rd16le(const uint8_t *p)
Read a little-endian u16 at p.
size_t pc_wr16le(uint8_t *p, uint16_t v)
Write v little-endian at p.