This commit is contained in:
orin
2026-07-30 08:45:38 +08:00
commit 25b24ac4cd
1333 changed files with 170092 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+233
View File
@@ -0,0 +1,233 @@
#ifndef MOTOR_CONTROL_H
#define MOTOR_CONTROL_H
#include <stdbool.h>
#include <stdint.h>
#define MOTOR_API_SUCCESS (0u)
#define MOTOR_API_FAILURE (1u)
#define MOTOR_PHYSICAL_VALUE_SCALE (100ul)
#define MOTOR_MODE0_DEFAULT_MAX_HALL_COUNT (480ul)
#define MOTOR_MODE0_MAX_POSITION_MM_X100 (10200ul)
#define MOTOR_MODE1_DEFAULT_MAX_HALL_COUNT (790ul)
#define MOTOR_MODE1_MAX_ANGLE_DEG_X100 (8500ul)
#define MOTOR_MODE2_DEFAULT_MAX_HALL_COUNT (1590ul)
#define MOTOR_MODE2_MAX_ANGLE_DEG_X100 (9000ul)
#define MOTOR_MODE3_DEFAULT_MAX_HALL_COUNT (960ul)
#define MOTOR_MODE3_MAX_POSITION_MM_X100 (24000ul)
#define MOTOR_SPEED_VALUE_SCALE (100ul)
#define MOTOR_SPEED_MIN_DUTY_PERCENT (50u)
#define MOTOR_SPEED_MAX_DUTY_PERCENT (95u)
#define MOTOR_SPEED_DUTY_STEP_PERCENT (5u)
#define MOTOR_MODE0_MAX_SPEED_PPS_X100 (8600ul)
#define MOTOR_MODE1_MAX_SPEED_PPS_X100 (6100ul)
#define MOTOR_MODE2_MAX_SPEED_PPS_X100 (9000ul)
#define MOTOR_MODE3_MAX_SPEED_PPS_X100 (8600ul)
typedef enum
{
MOTOR_MODE_0_LINEAR = 0,
MOTOR_MODE_1_ANGLE,
MOTOR_MODE_2_ANGLE,
MOTOR_MODE_3_LINEAR_TRACK,
MOTOR_MODE_COUNT
} motor_mode_t;
typedef enum
{
MOTOR_DIRECTION_STOPPED = 0,
MOTOR_DIRECTION_TOWARD_FAR,
MOTOR_DIRECTION_TOWARD_NEAR
} motor_direction_t;
typedef enum
{
MOTOR_EVENT_NONE = 0,
MOTOR_EVENT_TARGET_REACHED,
MOTOR_EVENT_NEAR_ENDPOINT,
MOTOR_EVENT_FAR_ENDPOINT,
MOTOR_EVENT_STALL,
MOTOR_EVENT_TIMEOUT,
MOTOR_EVENT_ABORTED,
MOTOR_EVENT_DRIVER_FAULT,
MOTOR_EVENT_CALIBRATION_FAILED
} motor_event_t;
typedef enum
{
MOTOR_CALIBRATE_FIND_NEAR = 0,
MOTOR_CALIBRATE_FIND_FAR,
MOTOR_CALIBRATE_FIND_BOTH
} motor_calibration_action_t;
typedef struct
{
motor_mode_t mode;
bool positionValid;
motor_direction_t direction;
motor_event_t lastEvent;
uint32_t hallCount;
uint32_t maxHallCount;
uint32_t valueX100;
uint32_t maxValueX100;
uint32_t positionMmX100;
uint32_t angleDegX100;
uint32_t percentX100;
} motor_position_info_t;
typedef struct
{
bool reverseAtEndpoint;
bool reverseAtStall;
} motor_safety_options_t;
typedef struct
{
bool nearEndpointFound;
bool farEndpointFound;
uint32_t measuredMaxHallCount;
} motor_calibration_result_t;
typedef struct
{
motor_mode_t mode;
bool enabled;
uint32_t durationMs;
uint32_t travelValueX100;
uint32_t plannedHallPulses;
uint32_t targetPulsesPerSecondX100;
uint32_t actualPulsesPerSecondX100;
uint8_t initialDutyPercent;
uint8_t currentDutyPercent;
} motor_speed_info_t;
typedef struct
{
uint32_t positionHallCount;
uint32_t maxHallCount;
uint32_t maxSpeedPulsesPerSecondX100;
uint32_t rawRisingEdges;
bool positionValid;
} motor_persistent_state_t;
/* Hardware initialization. SystemInit() and global IRQ enable remain owned by main. */
uint8_t Motor_Init(void);
/* Immediate GPIO-only safe state, also valid before Motor_Init(). */
void Motor_ForceSafeOff(void);
/* The Hall timebase is a precise 2 ms hardware interrupt. */
uint32_t Motor_GetTimeMs(void);
void Motor_SetWatchdogServiceEnabled(bool enabled);
/*
* Physical values use fixed point x100: 102.00 mm is 10200 and
* 85.25 degrees is 8525. positionValid is false until an endpoint has
* been found after power-up.
*
* Ownership contract: call all control APIs and Motor_ServiceAll from one
* main-loop/owner context. They are not ISR-safe, thread-safe, or reentrant.
* The four motors may still run concurrently after sequential non-blocking
* start calls from that owner.
*/
uint8_t Motor_GetPositionInfo(motor_mode_t mode, motor_position_info_t *info);
/* Each mode has independent endpoint and stall reverse switches. */
uint8_t Motor_SetSafetyOptions(motor_mode_t mode,
const motor_safety_options_t *options);
/* Open-loop primitives used by the standardized application controller. */
uint8_t Motor_SetFixedDutyPercent(motor_mode_t mode, uint8_t dutyPercent);
uint8_t Motor_StartOpenLoop(motor_mode_t mode, motor_direction_t direction);
bool Motor_IsMoving(motor_mode_t mode);
/*
* Restore/store Hall-domain state. These calls are accepted only while the
* selected motor is stopped. max speed uses Hall rising edges/s x100.
*/
uint8_t Motor_ApplyPersistentState(motor_mode_t mode,
const motor_persistent_state_t *state);
uint8_t Motor_GetPersistentState(motor_mode_t mode,
motor_persistent_state_t *state);
uint8_t Motor_SetMaximumSpeedPpsX100(motor_mode_t mode,
uint32_t maxSpeedPpsX100);
/*
* Pair an owner-context command with cancellation published asynchronously.
* An acknowledge succeeds when no cancellation is pending, or when sequence
* exactly matches it. It fails if a newer cancellation has already arrived.
*/
uint8_t Motor_AcknowledgeCommand(motor_mode_t mode, uint16_t sequence);
bool Motor_IsCommandCurrent(motor_mode_t mode, uint16_t sequence);
/*
* Start is non-blocking and permits all four modes to move concurrently.
* Wait and MoveToValue return 0 only after the target is reached; endpoint,
* stall, invalid position, invalid target, and timeout return 1.
* Replacing a target still ahead in the same direction does not restart PWM
* or refresh safety/timeout clocks. A direction change waits at least 100 ms
* and until Hall has been quiet for 100 ms. Crossing a target stops PWM once;
* residual Hall pulses remain in the global position and may leave the final
* count beyond the target. No automatic reverse correction is performed.
* If a safety reverse is enabled, Wait remains blocked until that reverse has
* stopped at its next safety event or at the absolute operation timeout.
*/
uint8_t Motor_StartMoveToValue(motor_mode_t mode, uint32_t targetValueX100);
uint8_t Motor_WaitForMove(motor_mode_t mode);
uint8_t Motor_MoveToValue(motor_mode_t mode, uint32_t targetValueX100);
uint8_t Motor_StopMode(motor_mode_t mode);
/*
* Configure closed-loop speed from a planned travel amount and duration.
* durationMs is milliseconds. travelValueX100 is mm x100 for mode 0 and
* degrees x100 for modes 1/2, and mm x100 for mode 3. This configures speed
* only; use an existing move API to start motion. After each real PWM start
* the controller waits
* 500 ms, then evaluates a 500 ms rolling Hall window every 100 ms. A speed
* error outside +/-10 percent changes that motor's duty by one 5 percent step.
*/
uint8_t Motor_SetSpeedPlan(motor_mode_t mode,
uint32_t durationMs,
uint32_t travelValueX100);
uint8_t Motor_DisableSpeedControl(motor_mode_t mode);
uint8_t Motor_GetSpeedInfo(motor_mode_t mode, motor_speed_info_t *info);
/*
* Calibration is blocking for the selected mode; other active modes continue.
* A new range is committed only after validation. Failure restores the old
* range, preserves observed motion, and invalidates absolute position because
* physical travel cannot be rolled back. Each leg requires Hall coast
* tracking to settle before/after travel; quiet wait is bounded to five seconds.
*/
uint8_t Motor_Calibrate(motor_mode_t mode,
motor_calibration_action_t action,
motor_calibration_result_t *result);
/* Call continuously from the main loop; the ISR still kills PWM immediately. */
void Motor_ServiceAll(void);
/* ISR-safe immediate PWM kill; bridge Hi-Z is completed by Motor_ServiceAll. */
void Motor_RequestAbortMaskFromIsr(uint8_t motorMask, uint16_t sequence);
void Motor_RequestAbortAllFromIsr(uint16_t sequence);
/* Irreversible until reset; unlike STOP, no sequence acknowledge can clear it. */
void Motor_LatchSafetyInhibitFromIsr(uint16_t sequence);
void Motor_StopAll(void);
/* A latched driver fault requires a power cycle before motion is accepted. */
bool Motor_IsDriverFaultLatched(void);
uint8_t Motor0_GetPosition(motor_position_info_t *info);
uint8_t Motor1_GetAngle(motor_position_info_t *info);
uint8_t Motor2_GetAngle(motor_position_info_t *info);
uint8_t Motor3_GetPosition(motor_position_info_t *info);
uint8_t Motor0_MoveToPositionMmX100(uint32_t positionMmX100);
uint8_t Motor1_MoveToAngleDegX100(uint32_t angleDegX100);
uint8_t Motor2_MoveToAngleDegX100(uint32_t angleDegX100);
uint8_t Motor3_MoveToPositionMmX100(uint32_t positionMmX100);
uint8_t Motor0_SetSpeedPlan(uint32_t durationMs, uint32_t distanceMmX100);
uint8_t Motor1_SetSpeedPlan(uint32_t durationMs, uint32_t angleDegX100);
uint8_t Motor2_SetSpeedPlan(uint32_t durationMs, uint32_t angleDegX100);
uint8_t Motor3_SetSpeedPlan(uint32_t durationMs, uint32_t distanceMmX100);
#endif /* MOTOR_CONTROL_H */