11#if DETWS_ENABLE_CIA402
16static size_t put16le(uint8_t *p, uint16_t v)
18 p[0] = (uint8_t)(v & 0xFF);
19 p[1] = (uint8_t)(v >> 8);
23static size_t put32le(uint8_t *p, uint32_t v)
25 p[0] = (uint8_t)(v & 0xFF);
26 p[1] = (uint8_t)((v >> 8) & 0xFF);
27 p[2] = (uint8_t)((v >> 16) & 0xFF);
28 p[3] = (uint8_t)((v >> 24) & 0xFF);
32static uint16_t get16le(
const uint8_t *p)
34 return (uint16_t)(p[0] | ((uint16_t)p[1] << 8));
37static uint32_t get32le(
const uint8_t *p)
39 return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24);
42Cia402State cia402_state(uint16_t sw)
45 if ((sw & 0x4F) == 0x00)
46 return Cia402State::not_ready_to_switch_on;
47 if ((sw & 0x4F) == 0x40)
48 return Cia402State::switch_on_disabled;
49 if ((sw & 0x6F) == 0x21)
50 return Cia402State::ready_to_switch_on;
51 if ((sw & 0x6F) == 0x23)
52 return Cia402State::switched_on;
53 if ((sw & 0x6F) == 0x27)
54 return Cia402State::operation_enabled;
55 if ((sw & 0x6F) == 0x07)
56 return Cia402State::quick_stop_active;
57 if ((sw & 0x4F) == 0x0F)
58 return Cia402State::fault_reaction_active;
59 if ((sw & 0x4F) == 0x08)
60 return Cia402State::fault;
61 return Cia402State::unknown;
64uint16_t cia402_controlword(Cia402Command cmd)
68 case Cia402Command::shutdown:
70 case Cia402Command::switch_on:
71 case Cia402Command::disable_operation:
73 case Cia402Command::enable_operation:
75 case Cia402Command::disable_voltage:
77 case Cia402Command::quick_stop:
79 case Cia402Command::fault_reset:
85uint16_t cia402_enable_sequence(Cia402State state)
89 case Cia402State::fault:
90 case Cia402State::fault_reaction_active:
91 return cia402_controlword(Cia402Command::fault_reset);
92 case Cia402State::switch_on_disabled:
93 return cia402_controlword(Cia402Command::shutdown);
94 case Cia402State::ready_to_switch_on:
95 return cia402_controlword(Cia402Command::switch_on);
96 case Cia402State::switched_on:
97 case Cia402State::quick_stop_active:
98 case Cia402State::operation_enabled:
99 return cia402_controlword(Cia402Command::enable_operation);
101 return cia402_controlword(Cia402Command::disable_voltage);
105bool cia402_sdo_set_controlword(
CanFrame *out, uint8_t node, uint16_t controlword)
108 put16le(d, controlword);
109 return canopen_build_sdo_write(out, node, CIA402_OD_CONTROLWORD, 0, d, 2);
112bool cia402_sdo_set_mode(
CanFrame *out, uint8_t node, Cia402Mode mode)
114 uint8_t d = (uint8_t)(int8_t)mode;
115 return canopen_build_sdo_write(out, node, CIA402_OD_MODES_OF_OPERATION, 0, &d, 1);
118bool cia402_sdo_set_target_position(
CanFrame *out, uint8_t node, int32_t position)
121 put32le(d, (uint32_t)position);
122 return canopen_build_sdo_write(out, node, CIA402_OD_TARGET_POSITION, 0, d, 4);
125bool cia402_sdo_set_target_velocity(
CanFrame *out, uint8_t node, int32_t velocity)
128 put32le(d, (uint32_t)velocity);
129 return canopen_build_sdo_write(out, node, CIA402_OD_TARGET_VELOCITY, 0, d, 4);
132bool cia402_sdo_set_target_torque(
CanFrame *out, uint8_t node, int16_t torque)
135 put16le(d, (uint16_t)torque);
136 return canopen_build_sdo_write(out, node, CIA402_OD_TARGET_TORQUE, 0, d, 2);
139bool cia402_sdo_read(
CanFrame *out, uint8_t node, uint16_t index, uint8_t sub)
141 return canopen_build_sdo_read(out, node, index, sub);
146static bool sdo_upload_bytes(
const CanFrame *f, uint16_t want_index, uint8_t need, uint8_t *out)
148 CanopenSdoResponse resp;
149 if (!canopen_parse_sdo_response(f, &resp))
151 if (resp.is_abort || !resp.is_upload || !resp.expedited || resp.len < need)
153 if (want_index != 0 && resp.index != want_index)
155 memcpy(out, resp.data, need);
159bool cia402_sdo_get_u16(
const CanFrame *f, uint16_t want_index, uint16_t *value)
162 if (!value || !sdo_upload_bytes(f, want_index, 2, d))
168bool cia402_sdo_get_i32(
const CanFrame *f, uint16_t want_index, int32_t *value)
171 if (!value || !sdo_upload_bytes(f, want_index, 4, d))
173 *value = (int32_t)get32le(d);
177size_t cia402_pack_command(uint8_t *buf,
size_t cap, uint16_t controlword, int32_t target)
181 size_t p = put16le(buf, controlword);
182 p += put32le(buf + p, (uint32_t)target);
186bool cia402_unpack_status(
const uint8_t *buf,
size_t len, uint16_t *statusword, int32_t *actual)
188 if (!buf || !statusword || !actual || len < 6)
190 *statusword = get16le(buf);
191 *actual = (int32_t)get32le(buf + 2);
CiA 402 / IEC 61800-7-201 drive + motion profile (DETWS_ENABLE_CIA402) over CANopen.