|
Motion Master 6.0.0-alpha.86
Next-generation motion control software
|
Borrowed view of a SOMANET drive — a CiA402 drive plus Synapticon-specific object-dictionary access (encoder/motor configuration, custom OS commands, etc.). More...
#include <somanet_drive.h>
Public Member Functions | |
| SomanetDrive (Device &device) | |
Binds an (unchecked) SOMANET view to device. Prefer createSomanetDrive. | |
| std::expected< OsCommandResponse, std::string > | runOsCommand (const std::vector< uint8_t > &command, const OsCommandConfig &config={}, const OsCommandFsBuffer &fsBuffer={}) |
| Issues an OS command (0x1023) and blocks until the drive reports it finished. | |
| std::expected< ObjectDictionaryValues, std::string > | readObjectDictionaryValues (const OsCommandConfig &config={}) |
| Reads every object dictionary value the drive holds, in one transfer (OS command 21). | |
| std::expected< std::string, std::string > | errorReport () const |
| Reads the drive's description of its most recent fault (0x203F:01). | |
| std::expected< BrakeState, std::string > | brakeState () const |
| Reads the whole brake configuration and its current state in one call. | |
| std::expected< somanet::BrakeStatus, std::string > | brakeStatus () const |
| Reads the brake state (0x2004:07). | |
| std::expected< void, std::string > | setBrakeStatus (somanet::BrakeStatus status) |
| Commands the brake by writing 0x2004:07 — the raw write, with no wait and no checks. | |
| std::expected< BrakeState, std::string > | releaseBrake (std::chrono::milliseconds settle=std::chrono::milliseconds(50)) |
| Releases (disengages) the brake, then waits for the release to finish. | |
| std::expected< BrakeState, std::string > | engageBrake (std::chrono::milliseconds settle=std::chrono::milliseconds(50)) |
Engages the brake and waits settle for it to bite. | |
| std::expected< void, std::string > | setOperationMode (somanet::OperationMode mode) |
| Requests one of SOMANET's manufacturer-specific operation modes (0x6060). | |
| std::expected< EncoderRegisterResult, std::string > | readEncoderRegister (somanet::EncoderOrdinal encoder, uint8_t registerAddress, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Reads one register of an encoder (OS command 0, read direction). | |
| std::expected< EncoderRegisterResult, std::string > | writeEncoderRegister (somanet::EncoderOrdinal encoder, uint8_t registerAddress, uint8_t value, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Writes one register of an encoder (OS command 0, write direction). | |
| std::expected< void, std::string > | setIcMuCalibrationMode (somanet::EncoderOrdinal encoder, somanet::IcMuCalibrationMode mode, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Sets an iC-MU encoder's calibration mode (OS command 1). | |
| std::expected< void, std::string > | configureHrdStream (somanet::HrdData data, std::chrono::milliseconds duration, const OsCommandConfig &config={.timeout=std::chrono::seconds(10),.pollInterval=std::chrono::milliseconds(100)}) |
| Configures a high resolution data stream (OS command 3, configure action). | |
| std::expected< void, std::string > | startHrdStream (const OsCommandConfig &config) |
| Starts the configured high resolution data stream and waits for it to finish (OS command 3, start action). | |
| std::expected< HrdRecording, std::string > | readHrdRecording (somanet::HrdData data) const |
| Reads the drive's high resolution data files back and decodes them (FoE, no OS command). | |
| std::expected< std::vector< DeviceFile >, std::string > | readFileList () const |
| Reads the list of files stored on the device (FoE read of "fs-getlist"). | |
| std::expected< HardwareDescription, std::string > | readHardwareDescription () const |
Reads and parses the drive's .hardware_description file (FoE). | |
| std::expected< std::optional< IntegroVariant >, std::string > | readIntegroVariant () const |
Reads and parses the drive's .variant file (FoE). | |
| std::expected< FullFirmwareDescriptors, std::string > | readFullFirmwareDescriptors () const |
| Reads both files and assembles the descriptors this drive accepts firmware under. | |
| std::expected< FirmwareCompatibility, std::string > | checkFirmwarePackage (std::string_view packageFilename) const |
Reads what this drive is and decides whether packageFilename belongs on it. | |
| std::expected< OpenPhaseResult, std::string > | runOpenPhaseDetection (const OsCommandConfig &config={.timeout=std::chrono::seconds(10),.pollInterval=std::chrono::milliseconds(100)}) |
| Runs open phase detection (OS command 6) and decodes its verdict. | |
| std::expected< MotorPhaseOrderResult, std::string > | runMotorPhaseOrderDetection (const OsCommandConfig &config={.timeout=std::chrono::seconds(60),.pollInterval=std::chrono::milliseconds(100)}) |
| Runs motor phase order detection (OS command 4) and decodes what it found. | |
| std::expected< somanet::CommutationOffsetMethod, std::string > | commutationOffsetMethod () const |
| Reads which commutation offset method is configured (0x2009:03). | |
| std::expected< CommutationOffsetResult, std::string > | runCommutationOffsetMeasurement (somanet::CommutationOffsetMethod method, const OsCommandConfig &config={.timeout=std::chrono::seconds(60),.pollInterval=std::chrono::milliseconds(100)}) |
| Runs commutation offset measurement (OS command 5) and decodes the offset it reports. | |
| std::expected< PolePairResult, std::string > | runPolePairDetection (const OsCommandConfig &config={.timeout=std::chrono::seconds(60),.pollInterval=std::chrono::milliseconds(100)}) |
| Runs pole pair detection (OS command 7) and decodes the count it reports. | |
| std::expected< PhaseResistanceResult, std::string > | runPhaseResistanceMeasurement (const OsCommandConfig &config={.timeout=std::chrono::seconds(30),.pollInterval=std::chrono::milliseconds(100)}) |
| Runs phase resistance measurement (OS command 8) and decodes the value it reports. | |
| std::expected< PhaseInductanceResult, std::string > | runPhaseInductanceMeasurement (const OsCommandConfig &config={.timeout=std::chrono::seconds(30),.pollInterval=std::chrono::milliseconds(100)}) |
| Runs phase inductance measurement (OS command 9) and decodes the value it reports. | |
| std::expected< TorqueConstantResult, std::string > | runTorqueConstantMeasurement (const OsCommandConfig &config={.timeout=std::chrono::seconds(60),.pollInterval=std::chrono::milliseconds(100)}) |
| Runs torque constant measurement (OS command 10) and decodes the value it reports. | |
| std::expected< TriggerErrorResult, std::string > | triggerError (somanet::FirmwareService service, somanet::FirmwareErrorType type, const OsCommandConfig &config={.timeout=std::chrono::seconds(3),.pollInterval=std::chrono::milliseconds(20)}) |
| Provokes a firmware error or exception in a control service (OS command 16). | |
| std::expected< KueblerRegisterResult, std::string > | accessKueblerRegister (uint8_t address, uint8_t length, bool write=false, uint32_t value=0, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Reads or writes one register of the Integro's internal (Kübler) encoder (command 19). | |
| std::expected< void, std::string > | setVelocitySource (somanet::VelocitySource source, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Chooses where the velocity control loop takes its feedback from (OS command 18). | |
| std::expected< void, std::string > | startFirmwareLatencyMeasurement (somanet::FirmwareLatency latency, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Starts measuring one internal firmware latency (OS command 22, action 0). | |
| std::expected< FirmwareLatencyResult, std::string > | readMaximumFirmwareLatency (somanet::FirmwareLatency latency, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Reads and clears one firmware latency's recorded maximum (OS command 22, action 1). | |
| std::expected< void, std::string > | stopFirmwareLatencyMeasurements (const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Stops measuring both firmware latencies (OS command 22, action 2). | |
| std::expected< SkippedCyclesResult, std::string > | readSkippedCycles (somanet::FirmwareService service, const OsCommandConfig &config={.timeout=std::chrono::seconds(30),.pollInterval=std::chrono::milliseconds(20)}) |
| Reads a control loop's skipped-cycle counter (OS command 13). | |
| std::expected< void, std::string > | setIgnoreBissStatusBits (somanet::EncoderOrdinal encoder, bool ignore, const OsCommandConfig &config={.timeout=std::chrono::seconds(30),.pollInterval=std::chrono::milliseconds(20)}) |
| Starts or stops ignoring a BiSS encoder's status bits (OS command 14). | |
| std::expected< void, std::string > | setSystemIdentificationParameter (somanet::SystemIdentificationParameter parameter, uint32_t value, const OsCommandConfig &config={.timeout=std::chrono::seconds(5),.pollInterval=std::chrono::milliseconds(20)}) |
| Writes one system-identification setting (OS command 15). | |
| std::expected< void, std::string > | setOperationMode (cia402::OperationMode mode) |
| Requests an operation mode (0x6060). The drive reflects it in 0x6061 once accepted. | |
Public Member Functions inherited from mm::node::Cia402Drive | |
| Cia402Drive (Device &device) | |
Binds an (unchecked) CiA402 view to device. Prefer createCia402Drive. | |
| std::expected< cia402::State, std::string > | state () const |
| Reads and decodes the current state machine state (statusword 0x6041). | |
| std::expected< uint16_t, std::string > | statusword () const |
| Reads the raw statusword (0x6041). | |
| std::expected< uint16_t, std::string > | controlword () const |
| Reads the last-commanded controlword (0x6040). | |
| std::expected< void, std::string > | setControlword (uint16_t value) |
| Writes the controlword (0x6040) verbatim. | |
| std::expected< cia402::OperationMode, std::string > | operationMode () const |
| Reads the active operation mode (display object 0x6061). | |
| std::expected< void, std::string > | setOperationMode (cia402::OperationMode mode) |
| Requests an operation mode (0x6060). The drive reflects it in 0x6061 once accepted. | |
| std::expected< int8_t, std::string > | operationModeValue () const |
| Reads the requested operation mode (0x6060) as its raw value. | |
| std::expected< int8_t, std::string > | operationModeValueDisplay () const |
Reads the active operation mode (0x6061) as its raw value — the display counterpart of operationModeValue, and the one that says what the drive actually took. | |
| std::expected< void, std::string > | setOperationModeValue (int8_t mode) |
Writes a raw operation-mode value to 0x6060 — the counterpart of operationModeValue. | |
| std::expected< void, std::string > | applyOperationMode (int8_t mode, std::chrono::milliseconds timeout=std::chrono::milliseconds(200)) |
Writes mode to 0x6060 and waits until the drive reports it active in 0x6061. | |
| std::expected< Cia402Status, std::string > | readStatus () const |
| Reads state, statusword, controlword, and the active mode in one shot. | |
| std::expected< void, std::string > | shutdown () |
| Shutdown: → ReadyToSwitchOn. | |
| std::expected< void, std::string > | switchOn () |
| Switch on: ReadyToSwitchOn → SwitchedOn (also disables operation from enabled). | |
| std::expected< void, std::string > | enableOperation () |
| Enable operation: SwitchedOn → OperationEnabled. | |
| std::expected< void, std::string > | disableVoltage () |
| Disable voltage: → SwitchOnDisabled. | |
| std::expected< void, std::string > | quickStop () |
| Quick stop: → QuickStopActive. | |
| std::expected< void, std::string > | faultReset () |
| Fault reset: asserts the rising edge of controlword bit 7 to clear a latched fault. | |
| std::expected< void, std::string > | transitionToState (cia402::State target, std::chrono::milliseconds timeout=std::chrono::milliseconds(2000), bool allowQuickStopOverride=false) |
Drives the state machine to target, walking every intermediate transition. | |
| std::expected< void, std::string > | enable (std::chrono::milliseconds timeout=std::chrono::milliseconds(2000)) |
| Drives the state machine to OperationEnabled. | |
| std::expected< void, std::string > | disable () |
| Brings the drive to SwitchOnDisabled (disable voltage). Single transition. | |
| std::expected< int32_t, std::string > | targetPosition () const |
| Reads the last-commanded target position (0x607A, INTEGER32). | |
| std::expected< void, std::string > | setTargetPosition (int32_t counts) |
| Writes target position (0x607A, INTEGER32) — CSP / PP. | |
| std::expected< int32_t, std::string > | targetVelocity () const |
| Reads the last-commanded target velocity (0x60FF, INTEGER32). | |
| std::expected< void, std::string > | setTargetVelocity (int32_t value) |
| Writes target velocity (0x60FF, INTEGER32) — CSV / PV. | |
| std::expected< int16_t, std::string > | targetTorque () const |
| Reads the last-commanded target torque (0x6071, INTEGER16, per-mille of rated). | |
| std::expected< void, std::string > | setTargetTorque (int16_t perMille) |
| Writes target torque (0x6071, INTEGER16, per-mille of rated) — CST / PT. | |
| std::expected< int32_t, std::string > | positionActualValue () const |
| Reads actual position (0x6064, INTEGER32). | |
| std::expected< int32_t, std::string > | velocityActualValue () const |
| Reads actual velocity (0x606C, INTEGER32). | |
| std::expected< int16_t, std::string > | torqueActualValue () const |
| Reads actual torque (0x6077, INTEGER16, per-mille of rated). | |
| std::expected< uint16_t, std::string > | errorCode () const |
| Reads the error code (0x603F, UNSIGNED16) — the code of the last drive fault. | |
| std::expected< int16_t, std::string > | quickStopOptionCode () const |
| Reads the quick stop option code (0x605A, INTEGER16). | |
| std::expected< void, std::string > | setQuickStopOptionCode (int16_t value) |
| Writes the quick stop option code (0x605A, INTEGER16) — the quick-stop reaction. | |
| std::expected< int32_t, std::string > | positionDemandValue () const |
| Reads the position demand value (0x6062, INTEGER32) — trajectory generator output. | |
| std::expected< uint32_t, std::string > | followingErrorWindow () const |
| Reads the following error window (0x6065, UNSIGNED32). | |
| std::expected< void, std::string > | setFollowingErrorWindow (uint32_t value) |
| Writes the following error window (0x6065, UNSIGNED32). | |
| std::expected< uint16_t, std::string > | followingErrorTimeout () const |
| Reads the following error time out (0x6066, UNSIGNED16, ms). | |
| std::expected< void, std::string > | setFollowingErrorTimeout (uint16_t value) |
| Writes the following error time out (0x6066, UNSIGNED16, ms). | |
| std::expected< uint32_t, std::string > | positionWindow () const |
| Reads the position window (0x6067, UNSIGNED32) — the target-reached tolerance. | |
| std::expected< void, std::string > | setPositionWindow (uint32_t value) |
| Writes the position window (0x6067, UNSIGNED32). | |
| std::expected< uint16_t, std::string > | positionWindowTime () const |
| Reads the position window time (0x6068, UNSIGNED16, ms). | |
| std::expected< void, std::string > | setPositionWindowTime (uint16_t value) |
| Writes the position window time (0x6068, UNSIGNED16, ms). | |
| std::expected< int32_t, std::string > | velocityDemandValue () const |
| Reads the velocity demand value (0x606B, INTEGER32) — ramp generator output. | |
| std::expected< uint16_t, std::string > | velocityWindow () const |
| Reads the velocity window (0x606D, UNSIGNED16) — the target-reached tolerance. | |
| std::expected< void, std::string > | setVelocityWindow (uint16_t value) |
| Writes the velocity window (0x606D, UNSIGNED16). | |
| std::expected< uint16_t, std::string > | velocityWindowTime () const |
| Reads the velocity window time (0x606E, UNSIGNED16, ms). | |
| std::expected< void, std::string > | setVelocityWindowTime (uint16_t value) |
| Writes the velocity window time (0x606E, UNSIGNED16, ms). | |
| std::expected< uint16_t, std::string > | velocityThreshold () const |
| Reads the velocity threshold (0x606F, UNSIGNED16) — the standstill threshold. | |
| std::expected< void, std::string > | setVelocityThreshold (uint16_t value) |
| Writes the velocity threshold (0x606F, UNSIGNED16). | |
| std::expected< uint16_t, std::string > | velocityThresholdTime () const |
| Reads the velocity threshold time (0x6070, UNSIGNED16, ms). | |
| std::expected< void, std::string > | setVelocityThresholdTime (uint16_t value) |
| Writes the velocity threshold time (0x6070, UNSIGNED16, ms). | |
| std::expected< uint16_t, std::string > | maxTorque () const |
| Reads max torque (0x6072, UNSIGNED16, per-mille of rated). | |
| std::expected< void, std::string > | setMaxTorque (uint16_t perMille) |
| Writes max torque (0x6072, UNSIGNED16, per-mille of rated). | |
| std::expected< uint16_t, std::string > | maxCurrent () const |
| Reads max current (0x6073, UNSIGNED16, per-mille of rated). | |
| std::expected< void, std::string > | setMaxCurrent (uint16_t perMille) |
| Writes max current (0x6073, UNSIGNED16, per-mille of rated). | |
| std::expected< int16_t, std::string > | torqueDemand () const |
| Reads the torque demand (0x6074, INTEGER16) — control loop output. | |
| std::expected< uint32_t, std::string > | motorRatedCurrent () const |
| Reads the motor rated current (0x6075, UNSIGNED32, mA). | |
| std::expected< void, std::string > | setMotorRatedCurrent (uint32_t milliamps) |
| Writes the motor rated current (0x6075, UNSIGNED32, mA). | |
| std::expected< uint32_t, std::string > | motorRatedTorque () const |
| Reads the motor rated torque (0x6076, UNSIGNED32, mNm). | |
| std::expected< void, std::string > | setMotorRatedTorque (uint32_t millinewtonMetres) |
| Writes the motor rated torque (0x6076, UNSIGNED32, mNm). | |
| std::expected< uint32_t, std::string > | dcLinkCircuitVoltage () const |
| Reads the DC link circuit voltage (0x6079, UNSIGNED32, mV). | |
| std::expected< PositionRangeLimit, std::string > | positionRangeLimit () const |
| Reads the position range limit (0x607B) — both sub-entries. | |
| std::expected< void, std::string > | setPositionRangeLimit (const PositionRangeLimit &limit) |
| Writes the position range limit (0x607B) — min then max; aborts on first failure. | |
| std::expected< int32_t, std::string > | homeOffset () const |
| Reads the home offset (0x607C, INTEGER32). | |
| std::expected< void, std::string > | setHomeOffset (int32_t value) |
| Writes the home offset (0x607C, INTEGER32). | |
| std::expected< SoftwarePositionLimit, std::string > | softwarePositionLimit () const |
| Reads the software position limit (0x607D) — both sub-entries. | |
| std::expected< void, std::string > | setSoftwarePositionLimit (const SoftwarePositionLimit &limit) |
| Writes the software position limit (0x607D) — min then max; aborts on first failure. | |
| std::expected< uint8_t, std::string > | polarity () const |
| Reads the polarity (0x607E, UNSIGNED8) — position/velocity inversion bits. | |
| std::expected< void, std::string > | setPolarity (uint8_t value) |
| Writes the polarity (0x607E, UNSIGNED8). | |
| std::expected< uint32_t, std::string > | maxMotorSpeed () const |
| Reads the max motor speed (0x6080, UNSIGNED32). | |
| std::expected< void, std::string > | setMaxMotorSpeed (uint32_t value) |
| Writes the max motor speed (0x6080, UNSIGNED32). | |
| std::expected< uint32_t, std::string > | profileVelocity () const |
| Reads the profile velocity (0x6081, UNSIGNED32) — PP cruise velocity. | |
| std::expected< void, std::string > | setProfileVelocity (uint32_t value) |
| Writes the profile velocity (0x6081, UNSIGNED32). | |
| std::expected< uint32_t, std::string > | profileAcceleration () const |
| Reads the profile acceleration (0x6083, UNSIGNED32). | |
| std::expected< void, std::string > | setProfileAcceleration (uint32_t value) |
| Writes the profile acceleration (0x6083, UNSIGNED32). | |
| std::expected< uint32_t, std::string > | profileDeceleration () const |
| Reads the profile deceleration (0x6084, UNSIGNED32). | |
| std::expected< void, std::string > | setProfileDeceleration (uint32_t value) |
| Writes the profile deceleration (0x6084, UNSIGNED32). | |
| std::expected< uint32_t, std::string > | quickStopDeceleration () const |
| Reads the quick stop deceleration (0x6085, UNSIGNED32). | |
| std::expected< void, std::string > | setQuickStopDeceleration (uint32_t value) |
| Writes the quick stop deceleration (0x6085, UNSIGNED32). | |
| std::expected< int16_t, std::string > | motionProfileType () const |
| Reads the motion profile type (0x6086, INTEGER16). | |
| std::expected< void, std::string > | setMotionProfileType (int16_t value) |
| Writes the motion profile type (0x6086, INTEGER16). | |
| std::expected< uint32_t, std::string > | torqueSlope () const |
| Reads the torque slope (0x6087, UNSIGNED32) — PT torque ramp rate. | |
| std::expected< void, std::string > | setTorqueSlope (uint32_t value) |
| Writes the torque slope (0x6087, UNSIGNED32). | |
| std::expected< int16_t, std::string > | torqueProfileType () const |
| Reads the torque profile type (0x6088, INTEGER16). | |
| std::expected< void, std::string > | setTorqueProfileType (int16_t value) |
| Writes the torque profile type (0x6088, INTEGER16). | |
| std::expected< GearRatio, std::string > | gearRatio () const |
| Reads the gear ratio (0x6091) — both sub-entries. | |
| std::expected< void, std::string > | setGearRatio (const GearRatio &ratio) |
| Writes the gear ratio (0x6091) — motor then shaft revolutions; aborts on first failure. | |
| std::expected< FeedConstant, std::string > | feedConstant () const |
| Reads the feed constant (0x6092) — both sub-entries. | |
| std::expected< void, std::string > | setFeedConstant (const FeedConstant &constant) |
| Writes the feed constant (0x6092) — feed then shaft revolutions; aborts on first failure. | |
| std::expected< int8_t, std::string > | homingMethod () const |
| Reads the homing method (0x6098, INTEGER8). | |
| std::expected< void, std::string > | setHomingMethod (int8_t method) |
| Writes the homing method (0x6098, INTEGER8). | |
| std::expected< HomingSpeeds, std::string > | homingSpeeds () const |
| Reads the homing speeds (0x6099) — both sub-entries. | |
| std::expected< void, std::string > | setHomingSpeeds (const HomingSpeeds &speeds) |
| Writes the homing speeds (0x6099) — switch then zero search; aborts on first failure. | |
| std::expected< uint32_t, std::string > | homingAcceleration () const |
| Reads the homing acceleration (0x609A, UNSIGNED32). | |
| std::expected< void, std::string > | setHomingAcceleration (uint32_t value) |
| Writes the homing acceleration (0x609A, UNSIGNED32). | |
| std::expected< uint32_t, std::string > | siUnitVelocity () const |
| Reads the SI unit velocity (0x60A9, UNSIGNED32) — the unit code of velocity objects. | |
| std::expected< void, std::string > | setSiUnitVelocity (uint32_t value) |
| Writes the SI unit velocity (0x60A9, UNSIGNED32). | |
| std::expected< int32_t, std::string > | velocityOffset () const |
| Reads the velocity offset (0x60B1, INTEGER32) — CSP/CSV velocity feed-forward. | |
| std::expected< void, std::string > | setVelocityOffset (int32_t value) |
| Writes the velocity offset (0x60B1, INTEGER32). | |
| std::expected< int16_t, std::string > | torqueOffset () const |
| Reads the torque offset (0x60B2, INTEGER16) — torque feed-forward. | |
| std::expected< void, std::string > | setTorqueOffset (int16_t value) |
| Writes the torque offset (0x60B2, INTEGER16). | |
| std::expected< uint16_t, std::string > | touchProbeFunction () const |
| Reads the touch probe function (0x60B8, UNSIGNED16) — arm/config bits. | |
| std::expected< void, std::string > | setTouchProbeFunction (uint16_t value) |
| Writes the touch probe function (0x60B8, UNSIGNED16). | |
| std::expected< uint16_t, std::string > | touchProbeStatus () const |
| Reads the touch probe status (0x60B9, UNSIGNED16) — latch status bits. | |
| std::expected< int32_t, std::string > | touchProbe1PositiveEdge () const |
| Reads the position latched at touch probe 1's rising edge (0x60BA, INTEGER32). | |
| std::expected< int32_t, std::string > | touchProbe1NegativeEdge () const |
| Reads the position latched at touch probe 1's falling edge (0x60BB, INTEGER32). | |
| std::expected< uint32_t, std::string > | touchProbeTimeStamp1PositiveValue () const |
| Reads the time stamp of touch probe 1's rising edge (0x60D1, UNSIGNED32). | |
| std::expected< uint32_t, std::string > | touchProbeTimeStamp1NegativeValue () const |
| Reads the time stamp of touch probe 1's falling edge (0x60D2, UNSIGNED32). | |
| std::expected< uint16_t, std::string > | positioningOptionCode () const |
| Reads the positioning option code (0x60F2, UNSIGNED16) — PP behaviour options. | |
| std::expected< void, std::string > | setPositioningOptionCode (uint16_t value) |
| Writes the positioning option code (0x60F2, UNSIGNED16). | |
| std::expected< int32_t, std::string > | followingErrorActualValue () const |
| Reads the following error actual value (0x60F4, INTEGER32). | |
| std::expected< int32_t, std::string > | controlEffort () const |
| Reads the control effort (0x60FA, INTEGER32) — position loop output. | |
| std::expected< int32_t, std::string > | positionDemandInternalValue () const |
| Reads the position demand internal value (0x60FC, INTEGER32). | |
| std::expected< uint32_t, std::string > | digitalInputs () const |
| Reads the digital inputs (0x60FD, UNSIGNED32) — input bit field. | |
| std::expected< DigitalOutputs, std::string > | digitalOutputs () const |
| Reads the digital outputs (0x60FE) — both sub-entries. | |
| std::expected< void, std::string > | setDigitalOutputs (const DigitalOutputs &outputs) |
| Writes the digital outputs (0x60FE) — levels first (inert while masked off), then the enable mask, so a newly enabled output comes up with its commanded level; aborts on first failure. | |
| std::expected< uint32_t, std::string > | supportedDriveModes () const |
| Reads the supported drive modes (0x6502, UNSIGNED32) — the capability bit field. Constant, so it is cached after the first read. | |
Public Member Functions inherited from mm::node::ProfileDevice | |
| ProfileDevice (Device &device) | |
Binds an (unchecked) view to device. Prefer createProfileDevice. | |
| Device & | device () |
| The underlying generic device this view operates on. | |
| const Device & | device () const |
| std::expected< uint32_t, std::string > | deviceType () const |
| Reads the device type (0x1000, UNSIGNED32) — the device profile the object dictionary implements (low word = profile number, e.g. 402; high word = profile-specific info). | |
| std::expected< uint8_t, std::string > | errorRegister () const |
| Reads the error register (0x1001, UNSIGNED8) — the active error class bit field (bit 0 = generic error). Read-only but volatile, so every call re-reads the device. | |
| std::expected< int32_t, std::string > | cobIdSync () const |
| Reads the COB-ID of the SYNC message (0x1005, INTEGER32). Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setCobIdSync (int32_t value) |
| Writes the COB-ID of the SYNC message (0x1005, INTEGER32). | |
| std::expected< int32_t, std::string > | communicationCyclePeriod () const |
| Reads the communication cycle period (0x1006, INTEGER32, µs). Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setCommunicationCyclePeriod (int32_t value) |
| Writes the communication cycle period (0x1006, INTEGER32, µs). | |
| std::expected< std::string, std::string > | manufacturerDeviceName () const |
| Reads the manufacturer device name (0x1008, VISIBLE_STRING). | |
| std::expected< std::string, std::string > | manufacturerSoftwareVersion () const |
| Reads the manufacturer software version (0x100A, VISIBLE_STRING) — the firmware version. | |
| std::expected< uint16_t, std::string > | guardTime () const |
| Reads the node guarding guard time (0x100C, UNSIGNED16, ms). Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setGuardTime (uint16_t value) |
| Writes the node guarding guard time (0x100C, UNSIGNED16, ms). | |
| std::expected< uint8_t, std::string > | lifeTimeFactor () const |
| Reads the node guarding life time factor (0x100D, UNSIGNED8). Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setLifeTimeFactor (uint8_t value) |
| Writes the node guarding life time factor (0x100D, UNSIGNED8). | |
| std::expected< uint32_t, std::string > | storeParameters () const |
| Reads "save all parameters" (0x1010:01, UNSIGNED32) — the save capability (bit 0 = device saves on command); writing the "save" signature to it triggers the store. Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setStoreParameters (uint32_t signature) |
| Writes "save all parameters" (0x1010:01, UNSIGNED32). Writing the ASCII "save" signature (0x65766173) commands the device to store its parameters to non-volatile memory; the device aborts any other value. | |
| std::expected< void, std::string > | runStoreParameters (const StoreParametersConfig &config={}) |
| Commands a parameter store (0x1010) and waits for the device to confirm it completed. | |
| std::expected< RestoreDefaultParameters, std::string > | restoreDefaultParameters () const |
| Reads the restore-default-parameters object (0x1011) — the restore capability of all four groups. Writable (the "load" signature triggers a restore), so every call re-reads the device. Fails if any sub-entry read fails. | |
| std::expected< void, std::string > | setRestoreAllDefaultParameters (uint32_t signature) |
| Writes "restore all default parameters" (0x1011:01, UNSIGNED32). Writing the ASCII "load" signature (0x64616F6C) commands the restore; the device aborts any other value. | |
| std::expected< void, std::string > | setRestoreCommunicationDefaultParameters (uint32_t signature) |
| Writes "restore communication default parameters" (0x1011:02, UNSIGNED32) — the ASCII "load" signature (0x64616F6C) commands the restore. | |
| std::expected< void, std::string > | setRestoreApplicationDefaultParameters (uint32_t signature) |
| Writes "restore application default parameters" (0x1011:03, UNSIGNED32) — the ASCII "load" signature (0x64616F6C) commands the restore. | |
| std::expected< void, std::string > | setRestoreManufacturerDefaultParameters (uint32_t signature) |
| Writes "restore manufacturer-defined default parameters" (0x1011:04, UNSIGNED32) — the ASCII "load" signature (0x64616F6C) commands the restore. | |
| std::expected< void, std::string > | runRestoreDefaultParameters (RestoreGroup group, const RestoreDefaultParametersConfig &config={}) |
| Commands a restore of default parameters (0x1011) and waits for the device to confirm. | |
| std::expected< uint32_t, std::string > | consumerHeartbeatTime () const |
| Reads the consumer heartbeat time (0x1016:01, UNSIGNED32, ms — node ID in bits 16-23). Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setConsumerHeartbeatTime (uint32_t value) |
| Writes the consumer heartbeat time (0x1016:01, UNSIGNED32, ms — node ID in bits 16-23). | |
| std::expected< uint16_t, std::string > | producerHeartbeatTime () const |
| Reads the producer heartbeat time (0x1017, UNSIGNED16, ms). Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setProducerHeartbeatTime (uint16_t value) |
| Writes the producer heartbeat time (0x1017, UNSIGNED16, ms). | |
| std::expected< Identity, std::string > | identity () const |
| Reads the identity object (0x1018) — vendor ID, product code, revision, serial. | |
| std::expected< uint8_t, std::string > | synchronousCounterOverflowValue () const |
| Reads the synchronous counter overflow value (0x1019, UNSIGNED8). Writable, so every call re-reads the device. | |
| std::expected< void, std::string > | setSynchronousCounterOverflowValue (uint8_t value) |
| Writes the synchronous counter overflow value (0x1019, UNSIGNED8). | |
| std::expected< std::vector< uint8_t >, std::string > | osCommand () const |
| Reads back the OS command bytes (0x1023:01, 8 bytes). Writable (this is the command the caller last issued), so every call re-reads the device. | |
| std::expected< void, std::string > | setOsCommand (const std::vector< uint8_t > &command) |
Writes the OS command bytes (0x1023:01, 8 bytes) — issues an OS command; poll osCommandStatus / osCommandResponse for the result. | |
| std::expected< uint8_t, std::string > | osCommandStatus () const |
| Reads the OS command status (0x1023:02, UNSIGNED8). Read-only but volatile (it tracks the last issued command), so every call re-reads the device. | |
| std::expected< std::vector< uint8_t >, std::string > | osCommandResponse () const |
| Reads the OS command response bytes (0x1023:03, 8 bytes). Read-only but volatile (it tracks the last issued command), so every call re-reads the device. | |
| std::expected< void, std::string > | setOsCommandMode (uint8_t mode) |
| Writes the OS command mode (0x1024, UNSIGNED8). Write-only on the device — there is no matching getter. | |
Additional Inherited Members | |
Protected Attributes inherited from mm::node::ProfileDevice | |
| Device & | device_ |
| The borrowed device — the only data member permitted in the whole view chain. | |
Borrowed view of a SOMANET drive — a CiA402 drive plus Synapticon-specific object-dictionary access (encoder/motor configuration, custom OS commands, etc.).
SOMANET drives implement CiA402 in full, so this is-a Cia402Drive and inherits the whole state machine and setpoint surface; it adds only the vendor-specific objects in the manufacturer range. Like every profile view it is a thin, stateless borrow over a Device (see ProfileDevice) — construct it for one operation and drop it.
Construct via createSomanetDrive, which checks the vendor ID before binding.
Multi-cycle procedures do not live here. Commutation-offset detection, auto-tuning, and the like are command-and-wait procedures that run off-RT on a background thread, taking a DeviceManager& and re-resolving their Device each step (a long-lived view would dangle across a bus rescan). Whoever owns that procedure runs it; this view's job is the synchronous, single-shot SOMANET object access that frames those procedures (reading/writing config, checking preconditions).
|
inlineexplicit |
Binds an (unchecked) SOMANET view to device. Prefer createSomanetDrive.
| std::expected< KueblerRegisterResult, std::string > mm::node::SomanetDrive::accessKueblerRegister | ( | uint8_t | address, |
| uint8_t | length, | ||
| bool | write = false, |
||
| uint32_t | value = 0, |
||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Reads or writes one register of the Integro's internal (Kübler) encoder (command 19).
The register map is somanet::kKueblerRegisters — the vendor's own draft — and this command addresses any byte, so a register the draft does not document is read as an unnamed one rather than refused.
The value is little-endian here, which of this family only this command and command 22 are. The reply puts the least significant byte first, and so does the write value. Reusing the big-endian decoder the measurements share would read every multi-byte register backwards.
length is bytes, 1 to 4, and it must match the register's real width — the encoder answers a mismatch with KueblerRegisterFault::kWrongByteCount rather than truncating. Which means the 64-bit register 0x04 cannot be read at all: the length byte caps at 4. See somanet::kMaxKueblerRegisterBytes.
A write is answered the same way a read is, by echoing the register's value, so a write confirms itself.
Preconditions: an Integro, with its internal encoder configured and not in bootloader mode.
| address | Register address. |
| length | Width in bytes, 1 to 4. |
| write | Write value rather than read. |
| value | The value to write, little-endian on the wire; ignored for a read. |
| config | Timing and cancellation. |
| std::expected< BrakeState, std::string > mm::node::SomanetDrive::brakeState | ( | ) | const |
Reads the whole brake configuration and its current state in one call.
| std::expected< somanet::BrakeStatus, std::string > mm::node::SomanetDrive::brakeStatus | ( | ) | const |
Reads the brake state (0x2004:07).
| std::expected< FirmwareCompatibility, std::string > mm::node::SomanetDrive::checkFirmwarePackage | ( | std::string_view | packageFilename | ) | const |
Reads what this drive is and decides whether packageFilename belongs on it.
The two FoE reads of readFullFirmwareDescriptors, then checkFirmwareCompatibility. An incompatible package is a verdict, not an error — the returned value carries both descriptors and a sentence naming them — so an error here means the question could not be asked: the filename is not a package name, or the hardware description could not be read.
Nothing acts on the answer: the firmware installation procedure writes whatever it is given, on purpose. This is for telling a user before they start.
| packageFilename | Bare package filename, with no directory part. |
| std::expected< somanet::CommutationOffsetMethod, std::string > mm::node::SomanetDrive::commutationOffsetMethod | ( | ) | const |
Reads which commutation offset method is configured (0x2009:03).
Worth reading before running command 5 rather than after, because the method decides whether the rotor will turn and whether the brake must be released or engaged — see somanet::requiresBrakeReleased. A value outside the defined 0-2 range is reported as an error rather than cast, since acting on a misread method would mean handling the brake the wrong way.
| std::expected< void, std::string > mm::node::SomanetDrive::configureHrdStream | ( | somanet::HrdData | data, |
| std::chrono::milliseconds | duration, | ||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(10), .pollInterval = std::chrono::milliseconds(100)} |
||
| ) |
Configures a high resolution data stream (OS command 3, configure action).
Chooses what the next recording captures and for how long, and deletes every HRD file already on the drive — which is the slow part: the firmware specification allows up to around 5 seconds for it in the worst case, so the default timeout is sized for that and not for a mailbox exchange.
Configuring does not record anything; startHrdStream does. They are separate commands precisely so a recording can be armed once and triggered when the machine is ready.
duration is validated against somanet::maxHrdStreamDuration before anything is sent. The drive checks it too and would answer HrdStreamFault::kDuration, so this is a courtesy rather than a safety net: it makes an out-of-range duration a caller error instead of a round trip, and keeps both limits stated in one place.
Needs no preparation — no diagnostics mode, no Operation Enabled, no brake, and nothing moves — only an active mailbox. What the data is worth does depend on preparation elsewhere: see somanet::HrdData, whose two selections each require another command to run first.
| data | Which signal the recording should capture. |
| duration | How long to record for; at most somanet::maxHrdStreamDuration(data). |
| config | Timing and cancellation. The default allows for the file deletion. |
| std::expected< BrakeState, std::string > mm::node::SomanetDrive::engageBrake | ( | std::chrono::milliseconds | settle = std::chrono::milliseconds(50) | ) |
Engages the brake and waits settle for it to bite.
Writes kEngaged to 0x2004:07 and waits. There is no pull time on the way in — the brake is spring-engaged, so engaging is removing voltage — so the wait is only settle. Like releaseBrake it does nothing when the strategy is kManualOutputVoltage.
| settle | How long to wait after commanding the brake before returning. |
| std::expected< std::string, std::string > mm::node::SomanetDrive::errorReport | ( | ) | const |
Reads the drive's description of its most recent fault (0x203F:01).
The one thing that turns a bare CiA402 Fault into an actionable message, which is why a procedure that finds a drive faulted mid-sequence reads it. Best-effort by nature: the object is manufacturer-specific and the string is short, so a caller should attach whatever it gets and carry on rather than treat a failed read as the real problem.
| std::expected< EncoderRegisterResult, std::string > mm::node::SomanetDrive::readEncoderRegister | ( | somanet::EncoderOrdinal | encoder, |
| uint8_t | registerAddress, | ||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Reads one register of an encoder (OS command 0, read direction).
The register communication the encoder's own service performs on the master's behalf — only BiSS implements it today, which is the command's one restriction along with the addressed encoder actually being configured. Both are enforced by the drive refusing the command, so a non-BiSS or unconfigured encoder comes back as an error rather than a bad reading.
Unlike the motor measurements this needs no preparation at all: no diagnostics mode, no Operation Enabled, no brake, and the shaft does not move. It needs only an active mailbox, so it works from PRE-OP up and can be run on a drive that is exchanging process data without disturbing it.
A refusal is an error and never a finding: this command either performs the transaction or does not. See somanet::EncoderRegisterFault for what its own error codes mean.
| encoder | Which configured encoder to address. |
| registerAddress | The register to read. |
| config | Timing and cancellation. The default is sized for this command. |
| std::expected< std::vector< DeviceFile >, std::string > mm::node::SomanetDrive::readFileList | ( | ) | const |
Reads the list of files stored on the device (FoE read of "fs-getlist").
Synapticon firmware serves its directory as a pseudo-file rather than through any standard service: reading the name fs-getlist over FoE returns one line per entry. That makes this a vendor operation despite looking like a filesystem primitive, which is why it lives here and not on Device beside readFile.
The listing is what makes readHrdRecording possible without guessing at filenames, and it is the answer to "what else is on this drive" for firmware, logs and the ESI.
| std::expected< FullFirmwareDescriptors, std::string > mm::node::SomanetDrive::readFullFirmwareDescriptors | ( | ) | const |
Reads both files and assembles the descriptors this drive accepts firmware under.
Two FoE reads, one of which is expected to fail on any drive that is not an Integro. The hardware description is required — without it there is no descriptor at all — so its failure is this call's failure.
| std::expected< HardwareDescription, std::string > mm::node::SomanetDrive::readHardwareDescription | ( | ) | const |
Reads and parses the drive's .hardware_description file (FoE).
This is how a device says what it is — its product id and revision, serial number, the components it is built from, and the assembly it was packaged into. It is also the only source of the descriptor that decides which firmware belongs on it, which is what most callers want it for (see checkFirmwareCompatibility).
Readable in BOOT as well as PRE-OP and above. The bootloader deliberately allows this one file, which is what lets a compatibility check work on a drive left stranded in BOOT by a failed install — precisely when knowing whether the package was the right one matters most.
| std::expected< HrdRecording, std::string > mm::node::SomanetDrive::readHrdRecording | ( | somanet::HrdData | data | ) | const |
Reads the drive's high resolution data files back and decodes them (FoE, no OS command).
Discovers the files from the device's own file list rather than guessing at their names, so a firmware that splits a recording across five files and one that keeps it in a single file are both read whole, and a device with no recording on it says so immediately instead of being probed for files that are not there.
The files are concatenated in numeric order and decoded as one stream — a sample may straddle a file boundary, since the firmware chunks a byte stream rather than padding each file to a whole number of samples.
data must be the selection the recording was made with. Nothing on the drive records it, so passing the other one silently reinterprets the bytes; the procedure that made the recording reports what it configured for exactly this reason.
Blocks for the transfer — five 8 KB FoE reads plus the list — on the calling thread. Requires an active mailbox.
| data | Which layout the files hold. |
| std::expected< std::optional< IntegroVariant >, std::string > mm::node::SomanetDrive::readIntegroVariant | ( | ) | const |
Reads and parses the drive's .variant file (FoE).
Only Integro drives carry one. A Node or a Circulo has none, so an empty optional is the normal answer rather than an error.
Any failure to read the file is taken as "there is none", because FoE cannot distinguish a missing file from a failed read. Reading the hardware description first is what makes that safe: its failure is fatal, so FoE is known to work by the time this runs.
A file that is read but does not decode is the one error — the device has a variant this build cannot make sense of.
| std::expected< FirmwareLatencyResult, std::string > mm::node::SomanetDrive::readMaximumFirmwareLatency | ( | somanet::FirmwareLatency | latency, |
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Reads and clears one firmware latency's recorded maximum (OS command 22, action 1).
The read is destructive and the measurement survives it: the drive answers with the maximum, then zeroes it, and goes on measuring. So consecutive reads each describe the window since the previous one rather than the whole run — which is what makes a maximum useful over time, and what means a read cannot be repeated to double-check a surprising figure.
Reading a latency that was never started answers zero for both numbers; see FirmwareLatencyResult.
| latency | Which latency to read. |
| config | Timing and cancellation. |
| std::expected< ObjectDictionaryValues, std::string > mm::node::SomanetDrive::readObjectDictionaryValues | ( | const OsCommandConfig & | config = {} | ) |
Reads every object dictionary value the drive holds, in one transfer (OS command 21).
The drive writes the raw bytes of its whole object dictionary to the fs-buffer while the command runs, and this decodes them against the entries the device reported when it was enumerated. ObjectDictionaryValues explains why that decode can go wrong and what stops it from going wrong quietly.
A test and a diagnostic, not the fast path for reading parameters. CoE Complete Access already reads a whole object in one transfer, which is what the parameter cache uses. What this adds is a second, independent reading of the same values, and the cheapest way to prove an fs-buffer transfer works on real hardware. It does reach two values SDO cannot: 0x1024, which is write-only, and 0x1023:01.
The transfer is about 2 KB and the drive sends 100 bytes per control cycle, so give it a timeout of a few hundred milliseconds rather than the default.
| config | Timing and cancellation (see OsCommandConfig). |
| std::expected< SkippedCyclesResult, std::string > mm::node::SomanetDrive::readSkippedCycles | ( | somanet::FirmwareService | service, |
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(30), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Reads a control loop's skipped-cycle counter (OS command 13).
How many cycles service failed to start on time since it began running. The firmware counts a cycle as skipped when it starts late enough to miss its slot, and adds the whole backlog when several are missed at once — so the figure is missed cycles, not missed deadlines. It is cumulative and nothing resets it, so read it twice and subtract: a counter that is large but unchanging describes a startup transient, and a small one that keeps climbing describes a drive that is still missing cycles now.
The two loops are counted separately and a request addressed at one says nothing about the other, which is why the service is a parameter rather than a detail.
The drive reports the same event twice, and the other half is easier to miss: when a cycle is skipped while a controller is enabled, the firmware also raises a CtrlCyEx warning that lands in the error report (0x203F). A rising counter with no warning means the cycles were skipped while the drive was disabled.
No preconditions. The command needs no operation mode, no CiA402 state and no brake, and it moves nothing — it is a pure read, safe to run on a drive that is enabled and moving.
| service | Which control loop to ask. |
| config | Timing and cancellation. The default timeout clears the drive's own ~20 s reception timeout (measured; see OsCommandError::kTimeout), so a firmware that does not run the addressed service answers for itself instead of being aborted from here first — which is the difference between "no such service" and a bare "this master gave up". The read itself takes one control cycle. |
| std::expected< BrakeState, std::string > mm::node::SomanetDrive::releaseBrake | ( | std::chrono::milliseconds | settle = std::chrono::milliseconds(50) | ) |
Releases (disengages) the brake, then waits for the release to finish.
Writes kDisengaged to 0x2004:07, then waits the drive's pull time (0x2004:03) plus settle before returning, because the firmware blocks motion — and motion-related OS commands — until the pull time expires. Release is open-loop: nothing confirms the brake actually let go, so that wait is the only margin there is, which is why settle is a parameter and not a constant.
Does nothing when the release strategy is kManualOutputVoltage (the brake is not firmware-controlled) or when it is already disengaged. That is not an error, and the returned state is how a caller tells: BrakeState::softwareControllable is false in the first case.
Two preconditions that make this a no-op rather than a failure if unmet, both from the SOMANET brake documentation: the release procedure runs only while the drive is in OP ENABLED, and in any other state the write merely energises phase D. In diagnostics mode entering OP ENABLED does not release the brake automatically the way normal operation does — which is exactly why a diagnostics procedure has to call this at all.
On a pin brake (kPin) this moves the shaft. The controller raises current progressively until the load lifts off the pin by the minimum displacement (0x2004:08), reversing direction if it reaches the current ceiling (0x2004:09, a percentage of rated current) first. Releasing a brake is not electrically passive on that strategy.
Control-plane only: it sleeps. Requires an active mailbox.
| settle | Extra wait on top of the drive's pull time. |
| std::expected< CommutationOffsetResult, std::string > mm::node::SomanetDrive::runCommutationOffsetMeasurement | ( | somanet::CommutationOffsetMethod | method, |
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(60), .pollInterval = std::chrono::milliseconds(100)} |
||
| ) |
Runs commutation offset measurement (OS command 5) and decodes the offset it reports.
A successful run reconfigures the drive: the firmware writes the measured offset into 0x2001 and sets 0x2009:01 to OFFSET_VALID, which is the point of running it — this is the measurement that commissions the axis.
Preconditions, all enforced by the drive refusing with OS error 251: operation mode somanet::OperationMode::kDiagnostics and CiA402 state Operation Enabled always, plus — for the rotating methods only — no limit switch active and the brake disengaged. Motor phase order detection (command 4) must also run first; that one the drive does not check.
Whether it turns the rotor depends on the configured method (0x2009:03), so a caller that never read the method does not know what this will do physically. kStationary does not turn it and needs the brake engaged; the two rotating methods turn it and need the brake released.
This command has no command-specific error codes, so a failure always carries a general one.
| method | The method read from the drive, recorded in the result so a reader of the value knows which measurement produced it. |
| config | Timing and cancellation. The default timeout is sized for this command. |
| std::expected< MotorPhaseOrderResult, std::string > mm::node::SomanetDrive::runMotorPhaseOrderDetection | ( | const OsCommandConfig & | config = {.timeout = std::chrono::seconds(60), .pollInterval = std::chrono::milliseconds(100)} | ) |
Runs motor phase order detection (OS command 4) and decodes what it found.
Determines whether the motor's phases are wired normally or inverted, by turning the rotor and comparing which way the sensor angle moves. A successful run reconfigures the drive: the firmware writes the detected order into 0x2003:05 itself, which is the point of running it — commutation offset measurement (command 5) requires it to run first.
Preconditions, all enforced by the drive refusing with OS error 251: operation mode somanet::OperationMode::kDiagnostics, CiA402 state Operation Enabled, no limit switch active, and the brake disengaged if one is configured (see releaseBrake — in diagnostics mode enabling the drive does not release it).
This command rotates the rotor. As with pole pair detection the specification states it outright rather than as a possibility.
This command has no command-specific error codes at all — a failure can only carry a general one (251 "command not allowed", 253 timeout, ...), so an error from here always names a reason the command did not run rather than something about the motor.
| config | Timing and cancellation. The default timeout is sized for this command. |
| std::expected< OpenPhaseResult, std::string > mm::node::SomanetDrive::runOpenPhaseDetection | ( | const OsCommandConfig & | config = {.timeout = std::chrono::seconds(10), .pollInterval = std::chrono::milliseconds(100)} | ) |
Runs open phase detection (OS command 6) and decodes its verdict.
Checks every motor terminal and FET leg for an open circuit. The drive answers success when nothing is open, and answers with a failed command whose command-specific error code names the offending terminal or FET when something is — so a failure here is a finding, and this returns it as an OpenPhaseResult value rather than an error. An error comes back only when the command could not be run or produced no verdict at all (a general OS error, a timeout, a cancellation, an SDO failure).
Preconditions, all of which the drive enforces by refusing with OS error 251 ("command not
allowed") rather than by misbehaving: operation mode somanet::OperationMode::kDiagnostics, CiA402 state Operation Enabled, and no limit switch active. A released brake is deliberately not among them. The firmware specification does not list one for this command, and says only that it "might rotate the motor if there is no brake, or if it's disengaged" — so an engaged brake does not prevent the check, it merely keeps the shaft still while it runs, which is the safer way to run it. Contrast pole pair (7) and motor phase order (4), whose restrictions do require a disengaged brake.
It may turn the motor if the brake is disengaged and nothing else holds the shaft.
| config | Timing and cancellation. The default timeout is sized for this command. |
| std::expected< OsCommandResponse, std::string > mm::node::SomanetDrive::runOsCommand | ( | const std::vector< uint8_t > & | command, |
| const OsCommandConfig & | config = {}, |
||
| const OsCommandFsBuffer & | fsBuffer = {} |
||
| ) |
Issues an OS command (0x1023) and blocks until the drive reports it finished.
The mechanism behind every typed SOMANET command: write the 8-byte request to 0x1023:01, poll 0x1023:03 until its status byte goes terminal, decode the response. The objects are CiA301, but everything about how they are driven is Synapticon firmware behaviour — the status mirrored into response byte 0, the 100-200 percentage band, the OS error code in byte 2, the eight-byte payloads — which is why this lives on the vendor view rather than on ProfileDevice beside the raw accessors it is built from.
Two firmware rules (both stated in the OS command specification) shape the implementation and are easy to break by "tidying" it:
No pre-check is made for a command already in progress: the drive enforces that itself by aborting the write to 0x1023:01 (SDO abort 0x08000021, "local control"), and that error is forwarded verbatim. Progress reported by the drive (status 100-200) is logged at debug level as it changes and is not otherwise surfaced — this call reports only the final outcome.
Blocks the calling thread for up to config.timeout (plus config.abortTimeout if the command has to be aborted). Control-plane only: it sleeps between polls, but each poll takes the driver's lock for one transaction, so it never blocks the RT loop. Requires the mailbox to be active (PRE-OP/SAFE-OP/OP).
A command that carries bulk data moves it through fsBuffer, after the write to 0x1023:01 and before the first poll. OsCommandFsBuffer explains why that position is not a choice.
A failed transfer is written down, and the poll runs anyway. The reason is that the drive usually gives the better answer. A command the firmware does not support writes nothing, so the FoE read gets no reply and fails with a bare timeout, while the drive is about to report "unsupported command". So the transfer's own error is returned in one case only: the drive reports that the command succeeded, and the payload the caller asked for is still missing.
| command | The 8-byte request: byte 0 is the OS command ID, bytes 1-7 its parameters. |
| config | Timing and cancellation (see OsCommandConfig). |
| fsBuffer | The bulk-data transfer, if the command has one (see OsCommandFsBuffer). |
OsCommandResponse::failed). An error string if the command was not run or produced no verdict: a malformed request, an SDO failure (forwarded as-is), an unknown status byte, a timeout, a cancellation, or an fs-buffer transfer that failed under a command the drive says succeeded. | std::expected< PhaseInductanceResult, std::string > mm::node::SomanetDrive::runPhaseInductanceMeasurement | ( | const OsCommandConfig & | config = {.timeout = std::chrono::seconds(30), .pollInterval = std::chrono::milliseconds(100)} | ) |
Runs phase inductance measurement (OS command 9) and decodes the value it reports.
The companion of runPhaseResistanceMeasurement in every respect that matters — same preconditions (diagnostics mode, Operation Enabled, no limit switch, and no brake requirement), same command-specific fault (somanet::PhaseMeasurementFault::kCurrentAmplitudeError), and a failure is likewise an error rather than a finding. Only the quantity differs: microhenries instead of milliohms.
It may turn the motor if the brake is disengaged and nothing else holds the shaft.
| config | Timing and cancellation. The default timeout is sized for this command. |
| std::expected< PhaseResistanceResult, std::string > mm::node::SomanetDrive::runPhaseResistanceMeasurement | ( | const OsCommandConfig & | config = {.timeout = std::chrono::seconds(30), .pollInterval = std::chrono::milliseconds(100)} | ) |
Runs phase resistance measurement (OS command 8) and decodes the value it reports.
Measures the resistance of one motor phase by driving current into the windings and observing what it takes. Unlike open phase detection, a failed command here is a plain failure and not a finding: this command either answers with a value or does not answer at all, so a refusal comes back as an error naming the reason — the drive's one command-specific code is somanet::PhaseMeasurementFault::kCurrentAmplitudeError, and a general code (251 "command
not allowed", 253 timeout, ...) is named too.
Preconditions, all enforced by the drive refusing with OS error 251: operation mode somanet::OperationMode::kDiagnostics, CiA402 state Operation Enabled, and no limit switch active. The brake is deliberately not among them — the firmware specification does not ask for it, and an engaged brake holding the shaft during the measurement is the safer state — so a caller should leave the brake alone rather than release it out of symmetry with the commands that do require it (motor phase order, pole pair).
It may turn the motor if the brake is disengaged and nothing else holds the shaft.
| config | Timing and cancellation. The default timeout is sized for this command. |
| std::expected< PolePairResult, std::string > mm::node::SomanetDrive::runPolePairDetection | ( | const OsCommandConfig & | config = {.timeout = std::chrono::seconds(60), .pollInterval = std::chrono::milliseconds(100)} | ) |
Runs pole pair detection (OS command 7) and decodes the count it reports.
Counts the connected motor's pole pairs by turning the rotor. A failed command is an error rather than a finding, as with the winding measurements: the command either answers with a count or does not answer at all.
Preconditions, all enforced by the drive refusing with OS error 251: operation mode somanet::OperationMode::kDiagnostics, CiA402 state Operation Enabled, no limit switch active, and the brake disengaged if one is configured. That last one is a real requirement here — unlike open phase detection and the winding measurements, whose restrictions omit it — because in diagnostics mode enabling the drive does not release the brake the way normal operation does, so a caller has to release it explicitly (see releaseBrake).
This command turns the rotor. Not "may": the specification says it needs to, so the shaft must be free to move and whatever it drives must be safe to move with it.
| config | Timing and cancellation. The default timeout is sized for this command. |
| std::expected< TorqueConstantResult, std::string > mm::node::SomanetDrive::runTorqueConstantMeasurement | ( | const OsCommandConfig & | config = {.timeout = std::chrono::seconds(60), .pollInterval = std::chrono::milliseconds(100)} | ) |
Runs torque constant measurement (OS command 10) and decodes the value it reports.
Measures how much torque the motor produces per ampere of effective (RMS) current. The drive cannot measure torque, so it measures the back-EMF instead — which is the same constant seen from the other side: it spins the motor open-loop up to a fixed electrical frequency, waits for the load to settle, and works the constant out from the voltage the motor generates at that speed.
The measurement is only as good as the drive's existing motor configuration. Subtracting the winding impedance from the applied voltage is what leaves the back-EMF, and the drive takes the resistance, the inductance and the pole pair count from 0x2003:03, :04 and :01 — not from anything measured during this command. Measure and store those first; a stale value there produces a wrong constant, silently, and a badly wrong one produces a negative (see TorqueConstantResult).
Preconditions, all enforced by the drive refusing with OS error 251: operation mode somanet::OperationMode::kDiagnostics, CiA402 state Operation Enabled, no limit switch active, and the brake disengaged if one is configured — the firmware groups this command with motor phase order and pole pair detection, not with the winding measurements.
This command turns the rotor, continuously and for the whole run. It is not a step or a fraction of a turn: the motor is spun up over about ten seconds and held there while the measurement is taken, so it is the longest-moving of the diagnostics commands.
The command has no command-specific error codes — a failure carries a general one, or none.
| config | Timing and cancellation. The default timeout is sized for this command. |
| std::expected< void, std::string > mm::node::SomanetDrive::setBrakeStatus | ( | somanet::BrakeStatus | status | ) |
Commands the brake by writing 0x2004:07 — the raw write, with no wait and no checks.
Prefer releaseBrake / engageBrake, which apply the timing the firmware requires. This is for restoring a previously captured status, where the point is to write exactly what was read.
| std::expected< void, std::string > mm::node::SomanetDrive::setIcMuCalibrationMode | ( | somanet::EncoderOrdinal | encoder, |
| somanet::IcMuCalibrationMode | mode, | ||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Sets an iC-MU encoder's calibration mode (OS command 1).
Restricted to a Circulo internal encoder — narrower than readEncoderRegister's BiSS-only rule — and to a configured encoder; the drive refuses anything else rather than misapplying it.
Like the register accesses this prepares nothing and moves nothing, needing only an active mailbox. Unlike them it leaves the encoder in the mode it set: there is no restoring counterpart, so an encoder put into kConfiguration or kRaw stays there until something puts it back to kStandard.
Two behaviours of the firmware worth knowing before sequencing calls, both of which make the order matter rather than being incidental: entering kConfiguration saves the current position, and entering kRaw uses that saved position as the starting point (raw data is relative) — so the motor must not move while in configuration mode if raw mode is to follow.
The command reports nothing on success, so there is no value to return; a mode value the sensor service does not recognise comes back as an error.
| encoder | Which configured encoder to address. |
| mode | The mode to put it in. |
| config | Timing and cancellation. The default is sized for this command. |
| std::expected< void, std::string > mm::node::SomanetDrive::setIgnoreBissStatusBits | ( | somanet::EncoderOrdinal | encoder, |
| bool | ignore, | ||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(30), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Starts or stops ignoring a BiSS encoder's status bits (OS command 14).
Every BiSS frame the encoder returns carries two status bits alongside the position, by which the encoder reports on its own reading. The firmware checks them each cycle and acts: a warning goes in the error report as BisWnBit, and an error faults the drive into active short circuit (BisErBit, reaction ASC — the phases are shorted whatever 0x605A says), and on an iC-MU it additionally reads the chip's status registers to find out why. Which bit pattern means what depends on the encoder's configured active level (0x2110/0x2112).
Ignoring them switches that whole check off for the addressed encoder: no warning, no fault, no register read. The drive then keeps running on an encoder that is saying its position is unreliable, which is why this exists for bringing up and diagnosing an encoder rather than for running a machine.
There is nothing to restore and nothing restores it. The flag lives in the BiSS service's memory, so it holds until another run turns it back on or the drive is power-cycled — it is not a mode that ends with the operation that set it.
Preconditions: the addressed encoder must be configured and be a BiSS encoder, because the BiSS service instance for that encoder is what answers. When it is not, nothing answers, and the drive reports OS error 253 after its whole ~20 s reception timeout — which this decodes into what actually happened rather than passing on a bare "timeout".
| encoder | Which encoder's status bits to act on. |
| ignore | True to stop the firmware acting on them, false to restore the default. |
| config | Timing and cancellation. The default timeout clears the drive's own ~20 s reception timeout, so an encoder that is not BiSS is reported as such. |
| std::expected< void, std::string > mm::node::Cia402Drive::setOperationMode | ( | cia402::OperationMode | mode | ) |
Requests an operation mode (0x6060). The drive reflects it in 0x6061 once accepted.
| std::expected< void, std::string > mm::node::SomanetDrive::setOperationMode | ( | somanet::OperationMode | mode | ) |
Requests one of SOMANET's manufacturer-specific operation modes (0x6060).
| std::expected< void, std::string > mm::node::SomanetDrive::setSystemIdentificationParameter | ( | somanet::SystemIdentificationParameter | parameter, |
| uint32_t | value, | ||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Writes one system-identification setting (OS command 15).
The command carries a parameter index and a 32-bit value, so a configured run is this called once per setting — there is no writing them together. The drive stores each as it arrives and answers immediately; nothing is checked at this point and nothing reads them back.
Validation happens later, and its failure is a drive fault. The firmware checks the configuration on the rising edge of SystemIdentificationParameter::kStartProcedure, inside the motion control loop — and a configuration outside somanet::kMinChirpFrequencyMilliHz and friends does not merely fail to start: it raises IvldPara with a quick-stop reaction. So every one of these writes succeeds, and a bad set of numbers surfaces as a faulted drive when it is armed. Check before writing, which is what parseSystemIdentificationRequest does.
The amplitude is not among the checked values — neither here nor in the firmware — and it is a torque command in per-mille of rated torque. Nothing will refuse an unreasonable one.
| parameter | Which setting to write. |
| value | Its value, in the units SystemIdentificationParameter names. |
| config | Timing and cancellation. |
| std::expected< void, std::string > mm::node::SomanetDrive::setVelocitySource | ( | somanet::VelocitySource | source, |
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Chooses where the velocity control loop takes its feedback from (OS command 18).
See somanet::VelocitySource for which source is the default, which is not what the OS command specification says: on an Integro build the firmware selects the encoder's own velocity at start-up, so a run asking for kEncoder there changes nothing and the informative direction is kFirmware.
No preconditions and nothing to restore. The command is accepted in any state, and the choice holds until another run changes it or the drive is power-cycled — nothing reports it back. It takes effect only for a configured Kübler encoder; on any other encoder it is accepted and does nothing.
It commands no motion, but it is not inert on a moving drive: the velocity loop's feedback changes under it, and the two sources do not agree exactly, so a closed loop can be disturbed by the switch.
| source | Which velocity to feed the loop. |
| config | Timing and cancellation. |
| std::expected< void, std::string > mm::node::SomanetDrive::startFirmwareLatencyMeasurement | ( | somanet::FirmwareLatency | latency, |
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Starts measuring one internal firmware latency (OS command 22, action 0).
Clears whatever that latency recorded and enables its measurement. The drive then keeps the maximum of every drive control cycle until stopFirmwareLatencyMeasurements ends it or the drive is power-cycled; the other latency is untouched either way.
Nothing reports whether a measurement is running, so starting one twice is indistinguishable from starting it once, except that the second start throws away what the first collected.
No preconditions and nothing to restore. The command is accepted in any state and moves nothing — the measurement is two timer reads and a comparison inside a cycle the drive was running anyway.
| latency | Which latency to measure. |
| config | Timing and cancellation. |
| std::expected< void, std::string > mm::node::SomanetDrive::startHrdStream | ( | const OsCommandConfig & | config | ) |
Starts the configured high resolution data stream and waits for it to finish (OS command 3, start action).
Blocks for the whole configured duration — up to ten seconds — because the drive holds the command in progress until the recording is complete, reporting its percentage as it goes. So config.timeout has to exceed the duration that was configured, and there is nothing in the start request that says what that duration is: the caller is the only one that knows, which is why this takes no arguments but needs its config sized deliberately.
Cancelling through config.stop aborts the recording on the drive like any other OS command, and the drive's two ways of stopping are not equivalent: finishing normally flushes the buffers it still holds before closing the stream, while an abort stops immediately and discards whatever is still buffered (up to 1004 bytes, so roughly 250 encoder samples or 167 velocity/torque ones). Everything already written to flash stays, so a cancelled recording is a short one rather than none — just short by more than the moment of cancelling.
| config | Timing and cancellation. Has no useful default — size the timeout from the duration that was configured. |
| std::expected< void, std::string > mm::node::SomanetDrive::stopFirmwareLatencyMeasurements | ( | const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} | ) |
Stops measuring both firmware latencies (OS command 22, action 2).
The command has no per-latency stop — one action disables both — so stopping one measurement necessarily ends the other. What each latency recorded is left alone and can still be read.
| config | Timing and cancellation. |
| std::expected< TriggerErrorResult, std::string > mm::node::SomanetDrive::triggerError | ( | somanet::FirmwareService | service, |
| somanet::FirmwareErrorType | type, | ||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(3), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Provokes a firmware error or exception in a control service (OS command 16).
A destructive test tool. Eight of the twelve error types do something a drive does not recover from on its own — see somanet::FirmwareErrorEffect — and this issues whichever it is asked for. It exists because the firmware does, and because reproducing a stopped service on purpose is how the behaviour around one gets tested.
What comes back depends on the type, and the result says which happened rather than guessing:
kNotImplemented — the firmware's case body is empty. The drive answers that the command failed and nothing happened. Seven of the twelve.kStopsService — the service executes faulty code or hangs and never answers again, so the command timing out is the intended outcome, reported as such rather than as a failure. The drive keeps its other services; the one addressed is gone until a power cycle. A drive that does answer means the error was not triggered.kRaisesResettableError — a DiagErr is reported and the drive reacts per 0x605A. It faults and a fault reset clears it.The two services do not answer this alike, and it is a firmware defect rather than a design. Motion control sets its failure status before the switch, so the resettable type overwrites it and answers success; drive control sets the same status after the switch, so it overwrites the success the resettable type just set and answers failure. The error is raised either way — only the status byte differs — so this reports on what the drive did, not on which byte came back.
| service | Which control loop to provoke. |
| type | Which error to raise. |
| config | Timing and cancellation. For a kStopsService type the timeout is how long to wait before concluding the service is gone, so it should be short. |
| std::expected< EncoderRegisterResult, std::string > mm::node::SomanetDrive::writeEncoderRegister | ( | somanet::EncoderOrdinal | encoder, |
| uint8_t | registerAddress, | ||
| uint8_t | value, | ||
| const OsCommandConfig & | config = {.timeout = std::chrono::seconds(5), .pollInterval = std::chrono::milliseconds(20)} |
||
| ) |
Writes one register of an encoder (OS command 0, write direction).
The counterpart of readEncoderRegister in every respect — same BiSS-only restriction, same absence of any preparation — and the drive answers it the same way, by reporting the register's value, so a write confirms itself.
A write reconfigures the encoder, and nothing here validates what is written. The register map belongs to the encoder chip, not to this firmware: a value that means one thing on an iC-MU means another elsewhere, and a wrong one can leave an encoder unable to report position. The one exception the firmware documents is the iC-MU soft reset — 0x07 into register 0x75 — which restarts the chip and is therefore acknowledged without a value (see EncoderRegisterResult::value).
| encoder | Which configured encoder to address. |
| registerAddress | The register to write. |
| value | The byte to write into it. |
| config | Timing and cancellation. The default is sized for this command. |