more code
This commit is contained in:
26
code/Core/Inc/crc.h
Normal file
26
code/Core/Inc/crc.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* crc.h
|
||||
*
|
||||
* Created on: 19 Dec 2025
|
||||
* Author: janik
|
||||
*/
|
||||
|
||||
#ifndef INC_CRC_H_
|
||||
#define INC_CRC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t crc;
|
||||
} CRC8_107;
|
||||
|
||||
static inline void CRC8_107_init(CRC8_107 *ctx)
|
||||
{
|
||||
ctx->crc = 0x0u;
|
||||
}
|
||||
|
||||
void CRC8_107_add(CRC8_107 *ctx, uint8_t data);
|
||||
uint8_t CRC8_107_getChecksum(const CRC8_107 *ctx);
|
||||
|
||||
#endif /* INC_CRC_H_ */
|
||||
140
code/Core/Inc/photon_protocol.h
Normal file
140
code/Core/Inc/photon_protocol.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* photon_protocol.h
|
||||
*
|
||||
* Created on: 19 Dec 2025
|
||||
* Author: janik
|
||||
*/
|
||||
|
||||
#ifndef INC_PHOTON_PROTOCOL_H_
|
||||
#define INC_PHOTON_PROTOCOL_H_
|
||||
|
||||
#define UUID_LENGTH 12 // 12 8bit values
|
||||
#define PHOTON_NETWORK_CONTROLLER_ADDRESS 0x00
|
||||
#define PHOTON_NETWORK_BROADCAST_ADDRESS 0xFF
|
||||
#define VENDOR_SPECIFIC_OPTIONS_LENGTH 16
|
||||
|
||||
|
||||
typedef enum {
|
||||
STATUS_OK = 0x00,
|
||||
STATUS_WRONG_FEEDER_ID = 0x01,
|
||||
STATUS_COULDNT_REACH = 0x02,
|
||||
STATUS_UNINITIALIZED_FEEDER = 0x03,
|
||||
STATUS_FEEDING_IN_PROGRESS = 0x04,
|
||||
STATUS_FAIL = 0x05,
|
||||
|
||||
STATUS_TIMEOUT = 0xFE,
|
||||
STATUS_UNKNOWN_ERROR = 0xFF
|
||||
} FeederStatus;
|
||||
|
||||
typedef enum {
|
||||
// Unicast Commands
|
||||
GET_FEEDER_ID = 0x01,
|
||||
INITIALIZE_FEEDER = 0x02,
|
||||
GET_VERSION = 0x03,
|
||||
MOVE_FEED_FORWARD = 0x04,
|
||||
MOVE_FEED_BACKWARD = 0x05,
|
||||
MOVE_FEED_STATUS = 0x06,
|
||||
|
||||
VENDOR_OPTIONS = 0xbf,
|
||||
|
||||
// Broadcast Commands
|
||||
GET_FEEDER_ADDRESS = 0xc0,
|
||||
IDENTIFY_FEEDER = 0xc1,
|
||||
PROGRAM_FEEDER_FLOOR = 0xc2,
|
||||
UNINITIALIZED_FEEDERS_RESPOND = 0xc3
|
||||
// EXTENDED_COMMAND = 0xff, Unused, reserved for future use
|
||||
} FeederCommand;
|
||||
|
||||
|
||||
|
||||
/* ---------- Packet Header ---------- */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t toAddress;
|
||||
uint8_t fromAddress;
|
||||
uint8_t packetId;
|
||||
uint8_t payloadLength;
|
||||
uint8_t crc;
|
||||
} PhotonPacketHeader;
|
||||
|
||||
/* ---------- Command Payloads ---------- */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t distance;
|
||||
} MoveCommand;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t uuid[UUID_LENGTH];
|
||||
} GetFeederAddressCommand;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t uuid[UUID_LENGTH];
|
||||
} InitializeFeederCommand;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t options[VENDOR_SPECIFIC_OPTIONS_LENGTH];
|
||||
} VendorOptionsCommand;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t uuid[UUID_LENGTH];
|
||||
uint8_t address;
|
||||
} ProgramFeederFloorAddressCommand;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t uuid[UUID_LENGTH];
|
||||
} IdentifyFeederCommand;
|
||||
|
||||
/* ---------- Full Command Packet ---------- */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
PhotonPacketHeader header;
|
||||
uint8_t commandId;
|
||||
union {
|
||||
MoveCommand move;
|
||||
GetFeederAddressCommand getFeederAddress;
|
||||
InitializeFeederCommand initializeFeeder;
|
||||
VendorOptionsCommand vendorOptions;
|
||||
ProgramFeederFloorAddressCommand programFeederFloorAddress;
|
||||
IdentifyFeederCommand identifyFeeder;
|
||||
} payload;
|
||||
} PhotonCommand;
|
||||
|
||||
/* ---------- Response Payloads ---------- */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t uuid[UUID_LENGTH];
|
||||
} GetFeederIdResponse;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t uuid[UUID_LENGTH];
|
||||
} InitializeFeederResponse;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t version;
|
||||
} GetProtocolVersionResponse;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint16_t expectedFeedTime;
|
||||
} FeedDistanceResponse;
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t options[VENDOR_SPECIFIC_OPTIONS_LENGTH];
|
||||
} VendorOptionsResponse;
|
||||
|
||||
/* ---------- Full Response Packet ---------- */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
PhotonPacketHeader header;
|
||||
uint8_t status;
|
||||
union {
|
||||
GetFeederIdResponse getFeederId;
|
||||
InitializeFeederResponse initializeFeeder;
|
||||
GetProtocolVersionResponse protocolVersion;
|
||||
FeedDistanceResponse expectedTimeToFeed;
|
||||
VendorOptionsResponse vendorOptions;
|
||||
} payload;
|
||||
} PhotonResponse;
|
||||
|
||||
|
||||
|
||||
#endif /* INC_PHOTON_PROTOCOL_H_ */
|
||||
137
code/Core/Inc/pid.h
Normal file
137
code/Core/Inc/pid.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* pid.h
|
||||
*
|
||||
* Created on: 19 Dec 2025
|
||||
* Author: janik
|
||||
*/
|
||||
|
||||
#ifndef INC_PID_H_
|
||||
#define INC_PID_H_
|
||||
|
||||
// pid_motor_wrap_i32.h
|
||||
typedef struct
|
||||
{
|
||||
// Gains
|
||||
int32_t kp;
|
||||
int32_t ki;
|
||||
int32_t kd;
|
||||
|
||||
// State
|
||||
int32_t integrator;
|
||||
int32_t prev_error;
|
||||
|
||||
// Limits
|
||||
int32_t integrator_min;
|
||||
int32_t integrator_max;
|
||||
int32_t out_max; // max |u|, e.g. 2400
|
||||
|
||||
// Slew limit
|
||||
int32_t max_output_step; // max |u(k) - u(k-1)| per control step
|
||||
int32_t last_output; // u(k-1)
|
||||
} pid_i32_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pwm; // 0..out_max
|
||||
uint8_t dir; // 0 or 1
|
||||
} pid_motor_cmd_t;
|
||||
|
||||
static inline int32_t clamp_i32(int32_t x, int32_t lo, int32_t hi)
|
||||
{
|
||||
if (x < lo) return lo;
|
||||
if (x > hi) return hi;
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void pid_init(pid_i32_t *pid,
|
||||
int32_t kp,
|
||||
int32_t ki,
|
||||
int32_t kd,
|
||||
int32_t integrator_min,
|
||||
int32_t integrator_max,
|
||||
int32_t out_max,
|
||||
int32_t max_output_step)
|
||||
{
|
||||
pid->kp = kp;
|
||||
pid->ki = ki;
|
||||
pid->kd = kd;
|
||||
|
||||
pid->integrator = 0;
|
||||
pid->prev_error = 0;
|
||||
|
||||
pid->integrator_min = integrator_min;
|
||||
pid->integrator_max = integrator_max;
|
||||
pid->out_max = out_max;
|
||||
|
||||
pid->max_output_step = max_output_step;
|
||||
pid->last_output = 0;
|
||||
}
|
||||
|
||||
static inline void pid_reset(pid_i32_t *pid)
|
||||
{
|
||||
pid->integrator = 0;
|
||||
pid->prev_error = 0;
|
||||
pid->last_output = 0;
|
||||
}
|
||||
|
||||
static inline pid_motor_cmd_t pid_update_motor(pid_i32_t *pid,
|
||||
int32_t setpoint,
|
||||
int32_t position)
|
||||
{
|
||||
pid_motor_cmd_t cmd;
|
||||
|
||||
// Basic PID (no overflow protection, as requested)
|
||||
int32_t error = setpoint - position;
|
||||
|
||||
int32_t p = pid->kp * error;
|
||||
|
||||
int32_t i = pid->integrator + pid->ki * error;
|
||||
i = clamp_i32(i, pid->integrator_min, pid->integrator_max);
|
||||
pid->integrator = i;
|
||||
|
||||
int32_t d_error = error - pid->prev_error;
|
||||
int32_t d = pid->kd * d_error;
|
||||
pid->prev_error = error;
|
||||
|
||||
// Raw control effort
|
||||
int32_t u_raw = p + i + d;
|
||||
|
||||
// Clamp to [-out_max, +out_max]
|
||||
if (u_raw > pid->out_max) u_raw = pid->out_max;
|
||||
if (u_raw < -pid->out_max) u_raw = -pid->out_max;
|
||||
|
||||
// ---------- Slew limit: avoid instant full reverse ----------
|
||||
int32_t u_prev = pid->last_output;
|
||||
int32_t u = u_raw;
|
||||
|
||||
int32_t max_step = pid->max_output_step;
|
||||
if (max_step > 0) {
|
||||
int32_t du = u_raw - u_prev;
|
||||
|
||||
if (du > max_step) {
|
||||
u = u_prev + max_step;
|
||||
} else if (du < -max_step) {
|
||||
u = u_prev - max_step;
|
||||
} else {
|
||||
u = u_raw;
|
||||
}
|
||||
}
|
||||
|
||||
// Save for next time
|
||||
pid->last_output = u;
|
||||
|
||||
// Map signed u to dir + pwm
|
||||
if (u >= 0) {
|
||||
cmd.dir = 1;
|
||||
cmd.pwm = (uint16_t)u;
|
||||
} else {
|
||||
cmd.dir = 0;
|
||||
cmd.pwm = (uint16_t)(-u);
|
||||
}
|
||||
|
||||
if (cmd.pwm > pid->out_max)
|
||||
cmd.pwm = (uint16_t)pid->out_max;
|
||||
|
||||
return cmd;
|
||||
}
|
||||
#endif /* INC_PID_H_ */
|
||||
@@ -53,6 +53,7 @@ void PendSV_Handler(void);
|
||||
void SysTick_Handler(void);
|
||||
void EXTI4_15_IRQHandler(void);
|
||||
void DMA1_Channel1_IRQHandler(void);
|
||||
void DMA1_Channel2_3_IRQHandler(void);
|
||||
void TIM14_IRQHandler(void);
|
||||
void TIM16_IRQHandler(void);
|
||||
void TIM17_IRQHandler(void);
|
||||
|
||||
Reference in New Issue
Block a user