undirbúningur falla fyrir can samskipti og prófun með lyklaborði
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
@startuml P4-architecture
|
||||||
|
' Project 4, Part 2.2: Layers of the reduced CANopen node (Node ID 1).
|
||||||
|
' Arrows point from the user to the thing it uses.
|
||||||
|
|
||||||
|
' skinparam packageStyle rectangle
|
||||||
|
skinparam classAttributeIconSize 0
|
||||||
|
hide empty members
|
||||||
|
|
||||||
|
package "Application layer (uses OSI 7)" {
|
||||||
|
class MotorController {
|
||||||
|
+ to_operational()
|
||||||
|
+ to_pre_operational()
|
||||||
|
+ to_stopped()
|
||||||
|
}
|
||||||
|
abstract class State
|
||||||
|
class SetpointGenerator
|
||||||
|
class PI_controller
|
||||||
|
}
|
||||||
|
|
||||||
|
package "CANopen layer (OSI 5-7)" {
|
||||||
|
class CanopenNode {
|
||||||
|
+ on_frame(frame)
|
||||||
|
+ poll(now_ms)
|
||||||
|
}
|
||||||
|
class SdoServer
|
||||||
|
class ObjectDictionary
|
||||||
|
interface NodeApplication {
|
||||||
|
+ on_nmt_command(cmd)
|
||||||
|
+ set_target_velocity(rpm)
|
||||||
|
+ get_velocity() : rpm
|
||||||
|
+ get_duty() : 0.1 %
|
||||||
|
}
|
||||||
|
interface CanBus {
|
||||||
|
+ send(frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package "Platform layer (Zephyr)" {
|
||||||
|
class ZephyrCanBus
|
||||||
|
class MotorDriver
|
||||||
|
class RotaryEncoderDriver
|
||||||
|
}
|
||||||
|
|
||||||
|
package "Hardware (OSI 1-2)" {
|
||||||
|
class "CAN controller + transceiver" as CAN
|
||||||
|
}
|
||||||
|
|
||||||
|
MotorController -> State
|
||||||
|
MotorController --> SetpointGenerator
|
||||||
|
MotorController --> PI_controller
|
||||||
|
MotorController ..|> NodeApplication
|
||||||
|
MotorController --> MotorDriver
|
||||||
|
MotorController --> RotaryEncoderDriver
|
||||||
|
|
||||||
|
CanopenNode --> SdoServer
|
||||||
|
SdoServer --> ObjectDictionary
|
||||||
|
CanopenNode --> ObjectDictionary
|
||||||
|
CanopenNode --> NodeApplication
|
||||||
|
CanopenNode --> CanBus
|
||||||
|
|
||||||
|
ZephyrCanBus ..|> CanBus
|
||||||
|
ZephyrCanBus --> CAN
|
||||||
|
|
||||||
|
note top of CanopenNode
|
||||||
|
NMT (0x000), boot-up (0x701),
|
||||||
|
RPDO1 (0x201), TPDO1 (0x181)
|
||||||
|
end note
|
||||||
|
|
||||||
|
note left of SdoServer
|
||||||
|
0x601 / 0x581, expedited only
|
||||||
|
abort codes 0x06020000, 0x08000022
|
||||||
|
end note
|
||||||
|
|
||||||
|
note right of ObjectDictionary
|
||||||
|
0x1000, 0x2000-0x2010, 0x606C,
|
||||||
|
0x6083, 0x6084, 0x60FF
|
||||||
|
access rules, little-endian packing
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
@startuml
|
||||||
|
' skinparam linetype ortho
|
||||||
|
' skinparam nodesep 100
|
||||||
|
skinparam ranksep 80
|
||||||
|
|
||||||
|
skinparam state {
|
||||||
|
BackgroundColor LightBlue
|
||||||
|
}
|
||||||
|
|
||||||
|
' hide empty members
|
||||||
|
|
||||||
|
Application <|-- CANopen
|
||||||
|
|
||||||
|
class Application {
|
||||||
|
{field} state machine
|
||||||
|
{field} controllers
|
||||||
|
{field} setpoint generator
|
||||||
|
{method} hello world
|
||||||
|
}
|
||||||
|
|
||||||
|
CANopen : Zephyr
|
||||||
|
|
||||||
|
Class01 <-- Class02
|
||||||
|
Class03 *-- Class04
|
||||||
|
Class05 o-- Class06
|
||||||
|
Class07 .. Class08
|
||||||
|
Class09 -- Class10
|
||||||
|
|
||||||
|
@enduml
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
@startuml
|
|
||||||
' skinparam linetype ortho
|
|
||||||
' skinparam nodesep 100
|
|
||||||
skinparam ranksep 80
|
|
||||||
|
|
||||||
skinparam state {
|
|
||||||
BackgroundColor LightBlue
|
|
||||||
}
|
|
||||||
|
|
||||||
[*] --> Initialization
|
|
||||||
|
|
||||||
state Initialization
|
|
||||||
Initialization : Entry / Stop motor
|
|
||||||
Initialization : Entry / Initialize internal parameters
|
|
||||||
Initialization : Entry / Reset speed measurement
|
|
||||||
Initialization : Do / Wait 2 seconds
|
|
||||||
Initialization : Exit / Send Boot-up message
|
|
||||||
|
|
||||||
state PreOperational
|
|
||||||
PreOperational : Entry / Stop motor
|
|
||||||
PreOperational : Do / Blink LED at 1 Hz
|
|
||||||
PreOperational : Do / Accept Kp and Ti configuration
|
|
||||||
PreOperational : Do / Select P or PI controller [c]
|
|
||||||
PreOperational : Exit / LED off
|
|
||||||
|
|
||||||
state Operational
|
|
||||||
Operational : Entry / LED on
|
|
||||||
Operational : Do / Run speed controller
|
|
||||||
Operational : Exit / Stop motor and LED off
|
|
||||||
|
|
||||||
state Stopped
|
|
||||||
Stopped : Entry / Stop motor
|
|
||||||
Stopped : Do / Blink LED at 2 Hz
|
|
||||||
Stopped : Exit / LED off
|
|
||||||
|
|
||||||
Initialization -r-> PreOperational : initialization\n complete
|
|
||||||
' Initialization -d-> Operational : initialization\n complete
|
|
||||||
|
|
||||||
PreOperational -d-> Operational : set operational [o]
|
|
||||||
PreOperational -l--> Initialization : reset [r]
|
|
||||||
|
|
||||||
Operational -u-> PreOperational : set pre-operational [p]
|
|
||||||
Operational -> Initialization : reset [r]
|
|
||||||
Operational --> Stopped : fault detected
|
|
||||||
|
|
||||||
Stopped -l-> Initialization : reset [r]
|
|
||||||
Stopped -> Operational : set operational [o]
|
|
||||||
Stopped -u-> PreOperational : set pre-operational [p]
|
|
||||||
|
|
||||||
@enduml
|
|
||||||
@@ -19,9 +19,11 @@ public:
|
|||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void command(char c) override;
|
// void command(char c) override;
|
||||||
|
|
||||||
void exit() override;
|
void exit() override;
|
||||||
|
|
||||||
|
NodeState id() const override { return NodeState::INITIALIZATION; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+40
-14
@@ -7,14 +7,15 @@
|
|||||||
#include "motor_driver.h"
|
#include "motor_driver.h"
|
||||||
#include "p_controller.h"
|
#include "p_controller.h"
|
||||||
#include "digital_out.h"
|
#include "digital_out.h"
|
||||||
|
#include "node_types.h"
|
||||||
|
#include "node_application.h"
|
||||||
|
|
||||||
class State;
|
class State;
|
||||||
|
|
||||||
|
class MotorController : public NodeApplication
|
||||||
class MotorController
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static constexpr double DEFAULT_REFERENCE_RPM = 25.0;
|
static constexpr double DEFAULT_TARGET_RPM = 0.0;
|
||||||
static constexpr double PWM_PER_PERCENT = 255.0 / 100.0;
|
static constexpr double PWM_PER_PERCENT = 255.0 / 100.0;
|
||||||
static constexpr uint8_t LED_PIN = Digital_out::STATUS_LED;
|
static constexpr uint8_t LED_PIN = Digital_out::STATUS_LED;
|
||||||
|
|
||||||
@@ -27,22 +28,32 @@ private:
|
|||||||
|
|
||||||
RotaryEncoderDriver &encoder;
|
RotaryEncoderDriver &encoder;
|
||||||
MotorDriver &motor;
|
MotorDriver &motor;
|
||||||
P_controller *controller;
|
|
||||||
|
P_controller &p_controller;
|
||||||
|
P_controller &pi_controller;
|
||||||
|
P_controller *controller; // Bendir á p_controller eða pi_controller
|
||||||
|
|
||||||
Digital_out led;
|
Digital_out led;
|
||||||
|
|
||||||
double reference_rpm;
|
double target_rpm; // Það sem beðið er um (RPDO1)
|
||||||
|
double reference_rpm; // Það sem stýringin fær
|
||||||
|
|
||||||
|
uint32_t profile_acceleration; // RPM/s
|
||||||
|
uint32_t profile_deceleration;
|
||||||
|
|
||||||
// Síðasta sýni, notað fyrir CSV-útprentun
|
// Síðasta sýni, notað fyrir CSV-útprentun
|
||||||
double last_actual_rpm;
|
double last_actual_rpm;
|
||||||
double last_pwm;
|
double last_pwm;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MotorController(
|
MotorController(
|
||||||
RotaryEncoderDriver &encoder,
|
RotaryEncoderDriver &encoder,
|
||||||
MotorDriver &motor,
|
MotorDriver &motor,
|
||||||
P_controller &controller,
|
P_controller &p_controller,
|
||||||
|
P_controller &pi_controller,
|
||||||
State &initialization,
|
State &initialization,
|
||||||
State &pre_operational,
|
State &pre_operational,
|
||||||
State &operational,
|
State &operational,
|
||||||
@@ -59,13 +70,15 @@ public:
|
|||||||
void transition_to(State &new_state);
|
void transition_to(State &new_state);
|
||||||
|
|
||||||
|
|
||||||
void to_initialization();
|
void to_initialization() override;
|
||||||
|
|
||||||
void to_pre_operational();
|
void to_pre_operational() override;
|
||||||
|
|
||||||
void to_operational();
|
void to_operational() override;
|
||||||
|
|
||||||
void to_stopped();
|
void to_stopped() override;
|
||||||
|
|
||||||
|
NodeState get_state() const override;
|
||||||
|
|
||||||
bool fault_active();
|
bool fault_active();
|
||||||
|
|
||||||
@@ -73,21 +86,34 @@ public:
|
|||||||
// Skilar true þegar nýtt sýni var keyrt í gegnum stýringuna
|
// Skilar true þegar nýtt sýni var keyrt í gegnum stýringuna
|
||||||
bool run_speed_controller();
|
bool run_speed_controller();
|
||||||
|
|
||||||
|
void set_target_rpm(double rpm) override { target_rpm = rpm; }
|
||||||
|
double get_target_rpm() const override { return target_rpm; }
|
||||||
double get_reference_rpm() const { return reference_rpm; }
|
double get_reference_rpm() const { return reference_rpm; }
|
||||||
double get_actual_rpm() const { return last_actual_rpm; }
|
double get_actual_rpm() const override { return last_actual_rpm; }
|
||||||
|
|
||||||
double get_pwm() const { return last_pwm; }
|
double get_pwm() const { return last_pwm; }
|
||||||
|
double get_duty_percent() const override { return last_pwm / PWM_PER_PERCENT; }
|
||||||
|
|
||||||
|
void set_profile_acceleration(uint32_t value) override {profile_acceleration = value; }
|
||||||
|
uint32_t get_profile_acceleration() const override { return profile_acceleration; }
|
||||||
|
void set_profile_deceleration(uint32_t value) override {profile_deceleration = value; }
|
||||||
|
uint32_t get_profile_deceleration() const override { return profile_deceleration; }
|
||||||
|
|
||||||
void stop_motor();
|
void stop_motor();
|
||||||
|
|
||||||
void reset_speed_measurement();
|
void reset_speed_measurement();
|
||||||
|
|
||||||
void reset_controller();
|
void reset_controller();
|
||||||
|
void reset_parameters() override;
|
||||||
|
|
||||||
void set_Kp(double value);
|
void set_Kp(double value) override;
|
||||||
|
double get_Kp() const override { return controller->get_Kp(); }
|
||||||
|
|
||||||
void set_Ti(double value);
|
bool set_Ti(double value) override;
|
||||||
|
double get_Ti() const override { return controller->get_Ti(); }
|
||||||
|
|
||||||
void set_controller(P_controller &new_controller);
|
void select_controller(ControllerType type) override;
|
||||||
|
ControllerType get_controller_type() const override;
|
||||||
|
|
||||||
void led_on();
|
void led_on();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef NODE_APPLICATION_H
|
||||||
|
#define NODE_APPLICATION_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "node_types.h"
|
||||||
|
|
||||||
|
class NodeApplication
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~NodeApplication() {}
|
||||||
|
|
||||||
|
// NMT
|
||||||
|
virtual void to_initialization() = 0;
|
||||||
|
virtual void to_pre_operational() = 0;
|
||||||
|
virtual void to_operational() = 0;
|
||||||
|
virtual void to_stopped() = 0;
|
||||||
|
virtual void reset_parameters() = 0;
|
||||||
|
virtual NodeState get_state() const = 0;
|
||||||
|
|
||||||
|
// 0x2000
|
||||||
|
virtual void select_controller(ControllerType type) = 0;
|
||||||
|
virtual ControllerType get_controller_type() const = 0;
|
||||||
|
|
||||||
|
// 0x2001
|
||||||
|
virtual void set_Kp(double value) = 0;
|
||||||
|
virtual double get_Kp() const = 0;
|
||||||
|
|
||||||
|
// 0x2002
|
||||||
|
virtual bool set_Ti(double value) = 0;
|
||||||
|
virtual double get_Ti() const = 0;
|
||||||
|
|
||||||
|
// 0x2010
|
||||||
|
virtual double get_duty_percent() const = 0;
|
||||||
|
|
||||||
|
// 0x606C
|
||||||
|
virtual double get_actual_rpm() const = 0;
|
||||||
|
|
||||||
|
// 0x6083
|
||||||
|
virtual void set_profile_acceleration(uint32_t value) = 0;
|
||||||
|
virtual uint32_t get_profile_acceleration() const = 0;
|
||||||
|
// 0x6084
|
||||||
|
virtual void set_profile_deceleration(uint32_t value) = 0;
|
||||||
|
virtual uint32_t get_profile_deceleration() const = 0;
|
||||||
|
|
||||||
|
// 0x60FF (RPDO1)
|
||||||
|
virtual void set_target_rpm(double value) = 0;
|
||||||
|
virtual double get_target_rpm() const = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef NODE_TYPES_H
|
||||||
|
#define NODE_TYPES_H
|
||||||
|
|
||||||
|
enum class ControllerType
|
||||||
|
{
|
||||||
|
P,
|
||||||
|
PI
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class NodeState
|
||||||
|
{
|
||||||
|
INITIALIZATION,
|
||||||
|
PRE_OPERATIONAL,
|
||||||
|
OPERATIONAL,
|
||||||
|
STOPPED
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -21,9 +21,11 @@ public:
|
|||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void command(char c) override;
|
// void command(char c) override;
|
||||||
|
|
||||||
void exit() override;
|
void exit() override;
|
||||||
|
|
||||||
|
NodeState id() const override { return NodeState::OPERATIONAL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,21 +5,27 @@ class P_controller
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
double Kp;
|
double Kp;
|
||||||
|
double default_Kp; // Gildið úr constructornum, notað af restore_defaults()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
P_controller(double Kp);
|
P_controller(double Kp);
|
||||||
virtual ~P_controller() {}
|
virtual ~P_controller() {}
|
||||||
virtual double update(double ref, double actual);
|
virtual double update(double ref, double actual);
|
||||||
virtual void reset() {}
|
virtual void reset() {}
|
||||||
|
virtual void restore_defaults(); //
|
||||||
|
virtual double get_Kp() const { return Kp; }
|
||||||
|
virtual double get_Ti() const { return 0.0; }
|
||||||
|
|
||||||
virtual void set_Kp(double value)
|
virtual void set_Kp(double value)
|
||||||
{
|
{
|
||||||
Kp = value;
|
Kp = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void set_Ti(double value)
|
virtual bool set_Ti(double value)
|
||||||
{
|
{
|
||||||
// P controller does not use Ti
|
// P controller does not use Ti
|
||||||
|
(void)value;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,17 @@ class PI_controller : public P_controller
|
|||||||
static constexpr double U_MIN = -100.0; // %
|
static constexpr double U_MIN = -100.0; // %
|
||||||
|
|
||||||
double Ti;
|
double Ti;
|
||||||
|
double default_Ti;
|
||||||
double T;
|
double T;
|
||||||
double integral;
|
double integral;
|
||||||
public:
|
public:
|
||||||
PI_controller(double Kp, double Ti, double T);
|
PI_controller(double Kp, double Ti, double T);
|
||||||
double update(double ref, double actual) override;
|
double update(double ref, double actual) override;
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
void restore_defaults() override;
|
||||||
|
|
||||||
void set_Ti(double value) override;
|
bool set_Ti(double value) override;
|
||||||
|
double get_Ti() const override { return Ti; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,14 +4,14 @@
|
|||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
|
||||||
class P_controller;
|
// class P_controller;
|
||||||
|
|
||||||
class PreOperationalState : public State
|
class PreOperationalState : public State
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
P_controller &p_controller;
|
// P_controller &p_controller;
|
||||||
P_controller &pi_controller;
|
// P_controller &pi_controller;
|
||||||
bool pi_selected;
|
// bool pi_selected;
|
||||||
|
|
||||||
int64_t previous_time;
|
int64_t previous_time;
|
||||||
bool led_state;
|
bool led_state;
|
||||||
@@ -21,7 +21,8 @@ private:
|
|||||||
{
|
{
|
||||||
NONE,
|
NONE,
|
||||||
ENTER_KP,
|
ENTER_KP,
|
||||||
ENTER_TI
|
ENTER_TI,
|
||||||
|
ENTER_RPM
|
||||||
};
|
};
|
||||||
|
|
||||||
InputMode input_mode;
|
InputMode input_mode;
|
||||||
@@ -30,12 +31,15 @@ private:
|
|||||||
uint8_t input_index;
|
uint8_t input_index;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PreOperationalState(P_controller& p_controller, P_controller& pi_controller);
|
// PreOperationalState(P_controller& p_controller, P_controller& pi_controller);
|
||||||
|
PreOperationalState();
|
||||||
|
|
||||||
void enter() override;
|
void enter() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
void command(char c) override;
|
// void command(char c) override;
|
||||||
void exit() override;
|
void exit() override;
|
||||||
|
|
||||||
|
NodeState id() const override { return NodeState::PRE_OPERATIONAL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+5
-1
@@ -1,6 +1,8 @@
|
|||||||
#ifndef STATE_H
|
#ifndef STATE_H
|
||||||
#define STATE_H
|
#define STATE_H
|
||||||
|
|
||||||
|
#include "node_types.h"
|
||||||
|
|
||||||
class MotorController;
|
class MotorController;
|
||||||
|
|
||||||
class State
|
class State
|
||||||
@@ -22,9 +24,11 @@ public:
|
|||||||
|
|
||||||
virtual void update() = 0; // run motor controller
|
virtual void update() = 0; // run motor controller
|
||||||
|
|
||||||
virtual void command(char c) = 0; // Listen for reset
|
// virtual void command(char c) = 0; // Listen for reset
|
||||||
|
|
||||||
virtual void exit() = 0; // Stop motor
|
virtual void exit() = 0; // Stop motor
|
||||||
|
|
||||||
|
virtual NodeState id() const = 0; //
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ public:
|
|||||||
|
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
void command(char c) override;
|
// void command(char c) override;
|
||||||
|
|
||||||
void exit() override;
|
void exit() override;
|
||||||
|
|
||||||
|
NodeState id() const override { return NodeState::STOPPED; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+9
-9
@@ -24,18 +24,18 @@ upload_flags =
|
|||||||
|
|
||||||
; Part 2.1: CAN bring-up test (src/can_send_test.c) instead of the motor app.
|
; Part 2.1: CAN bring-up test (src/can_send_test.c) instead of the motor app.
|
||||||
; Build/upload: pio run -e can_test -t upload
|
; Build/upload: pio run -e can_test -t upload
|
||||||
[env:can_test]
|
; [env:can_test]
|
||||||
extends = env:nucleo_l432kc
|
; extends = env:nucleo_l432kc
|
||||||
build_flags = -D CAN_SEND_TEST=1
|
; build_flags = -D CAN_SEND_TEST=1
|
||||||
|
|
||||||
; L4.4 example (src/CAN_FRAME_TEST.c) instead of the motor app.
|
; L4.4 example (src/CAN_FRAME_TEST.c) instead of the motor app.
|
||||||
; Build/upload: pio run -e can_frame_test -t upload
|
; Build/upload: pio run -e can_frame_test -t upload
|
||||||
[env:can_frame_test]
|
; [env:can_frame_test]
|
||||||
extends = env:nucleo_l432kc
|
; extends = env:nucleo_l432kc
|
||||||
build_flags = -D CAN_FRAME_TEST=1
|
; build_flags = -D CAN_FRAME_TEST=1
|
||||||
|
|
||||||
; CAN reception with a filter (src/can_rx_test.c) instead of the motor app.
|
; CAN reception with a filter (src/can_rx_test.c) instead of the motor app.
|
||||||
; Build/upload: pio run -e can_rx_test -t upload
|
; Build/upload: pio run -e can_rx_test -t upload
|
||||||
[env:can_rx_test]
|
; [env:can_rx_test]
|
||||||
extends = env:nucleo_l432kc
|
; extends = env:nucleo_l432kc
|
||||||
build_flags = -D CAN_RX_TEST=1
|
; build_flags = -D CAN_RX_TEST=1
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ void can_frame_test_main(void)
|
|||||||
|
|
||||||
struct can_frame frame = {
|
struct can_frame frame = {
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.id = 0x123,
|
.id = 0x456,
|
||||||
.dlc = 8,
|
.dlc = 4,
|
||||||
.data = {1, 2, 3, 4, 5, 6, 7, 8},
|
.data = {1, 2, 3, 4, 5, 6, 7, 8},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -34,7 +34,7 @@ static PI_controller pi_controller(Kp, Ti, T);
|
|||||||
|
|
||||||
static InitializationState initialization_state;
|
static InitializationState initialization_state;
|
||||||
// Pre-operational velur á milli stýringanna með 'c'
|
// Pre-operational velur á milli stýringanna með 'c'
|
||||||
static PreOperationalState pre_operational_state(p_controller, pi_controller);
|
static PreOperationalState pre_operational_state;
|
||||||
static OperationalState operational_state;
|
static OperationalState operational_state;
|
||||||
static StoppedState stopped_state;
|
static StoppedState stopped_state;
|
||||||
|
|
||||||
@@ -42,6 +42,7 @@ static StoppedState stopped_state;
|
|||||||
static MotorController motor_controller(
|
static MotorController motor_controller(
|
||||||
encoder,
|
encoder,
|
||||||
motor,
|
motor,
|
||||||
|
p_controller,
|
||||||
pi_controller, // Sjálfgefin stýring
|
pi_controller, // Sjálfgefin stýring
|
||||||
initialization_state,
|
initialization_state,
|
||||||
pre_operational_state,
|
pre_operational_state,
|
||||||
@@ -107,6 +108,15 @@ extern "C" void motor_application_main(void)
|
|||||||
|
|
||||||
motor_controller.update();
|
motor_controller.update();
|
||||||
|
|
||||||
|
static NodeState last_state = NodeState::INITIALIZATION;
|
||||||
|
|
||||||
|
const NodeState now = motor_controller.get_state();
|
||||||
|
if (now != last_state)
|
||||||
|
{
|
||||||
|
printk("get_state: %d -> %d\n", (int)last_state, (int)now);
|
||||||
|
last_state = now;
|
||||||
|
}
|
||||||
|
|
||||||
// Sleep until the encoder has a new speed sample (every 4 ms), so
|
// Sleep until the encoder has a new speed sample (every 4 ms), so
|
||||||
// the controller runs right after sampling. The timeout only
|
// the controller runs right after sampling. The timeout only
|
||||||
// matters if the timer stops; the thread is idle while it waits.
|
// matters if the timer stops; the thread is idle while it waits.
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
MotorController::MotorController(
|
MotorController::MotorController(
|
||||||
RotaryEncoderDriver &encoder,
|
RotaryEncoderDriver &encoder,
|
||||||
MotorDriver &motor,
|
MotorDriver &motor,
|
||||||
P_controller &controller,
|
P_controller &p_controller,
|
||||||
|
P_controller &pi_controller,
|
||||||
State &initialization,
|
State &initialization,
|
||||||
State &pre_operational,
|
State &pre_operational,
|
||||||
State &operational,
|
State &operational,
|
||||||
@@ -17,9 +18,14 @@ MotorController::MotorController(
|
|||||||
stopped_state(stopped),
|
stopped_state(stopped),
|
||||||
encoder(encoder),
|
encoder(encoder),
|
||||||
motor(motor),
|
motor(motor),
|
||||||
controller(&controller),
|
p_controller(p_controller),
|
||||||
|
pi_controller(pi_controller),
|
||||||
|
controller(&pi_controller), // PI er sjálfgefin stýring
|
||||||
led(LED_PIN),
|
led(LED_PIN),
|
||||||
reference_rpm(DEFAULT_REFERENCE_RPM),
|
target_rpm(DEFAULT_TARGET_RPM),
|
||||||
|
reference_rpm(DEFAULT_TARGET_RPM),
|
||||||
|
profile_acceleration(0),
|
||||||
|
profile_deceleration(0),
|
||||||
last_actual_rpm(0.0),
|
last_actual_rpm(0.0),
|
||||||
last_pwm(0.0)
|
last_pwm(0.0)
|
||||||
{
|
{
|
||||||
@@ -92,6 +98,8 @@ bool MotorController::run_speed_controller()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reference_rpm = target_rpm;
|
||||||
|
|
||||||
const double actual = encoder.rpm();
|
const double actual = encoder.rpm();
|
||||||
|
|
||||||
const double pwm_percent =
|
const double pwm_percent =
|
||||||
@@ -135,28 +143,71 @@ void MotorController::reset_controller()
|
|||||||
controller->reset();
|
controller->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MotorController::reset_parameters()
|
||||||
|
{
|
||||||
|
p_controller.restore_defaults();
|
||||||
|
pi_controller.restore_defaults();
|
||||||
|
|
||||||
|
select_controller(ControllerType::PI);
|
||||||
|
set_target_rpm(DEFAULT_TARGET_RPM);
|
||||||
|
|
||||||
|
set_profile_acceleration(0);
|
||||||
|
set_profile_deceleration(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MotorController::set_Kp(double value)
|
void MotorController::set_Kp(double value)
|
||||||
{
|
{
|
||||||
controller->set_Kp(value);
|
controller->set_Kp(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorController::set_Ti(double value)
|
bool MotorController::set_Ti(double value)
|
||||||
{
|
{
|
||||||
controller->set_Ti(value);
|
return controller->set_Ti(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorController::set_controller(P_controller& new_controller)
|
void MotorController::select_controller(ControllerType type)
|
||||||
{
|
{
|
||||||
controller = &new_controller;
|
if (type == ControllerType::PI)
|
||||||
|
{
|
||||||
|
controller = &pi_controller;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
controller = &p_controller;
|
||||||
|
}
|
||||||
|
|
||||||
controller->reset();
|
controller->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ControllerType MotorController::get_controller_type() const
|
||||||
|
{
|
||||||
|
if (controller == &pi_controller)
|
||||||
|
{
|
||||||
|
return ControllerType::PI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ControllerType::P;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MotorController::to_stopped()
|
void MotorController::to_stopped()
|
||||||
{
|
{
|
||||||
transition_to(stopped_state);
|
transition_to(stopped_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodeState MotorController::get_state() const
|
||||||
|
{
|
||||||
|
if (current_state == nullptr)
|
||||||
|
{
|
||||||
|
return NodeState::INITIALIZATION;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return current_state->id();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MotorController::fault_active()
|
bool MotorController::fault_active()
|
||||||
{
|
{
|
||||||
return motor.fault_active();
|
return motor.fault_active();
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ void OperationalState::enter()
|
|||||||
|
|
||||||
sample_count = 0;
|
sample_count = 0;
|
||||||
|
|
||||||
|
// Tímabundið til þess að prófa undirbúning CAN communication
|
||||||
|
printk("Kp=%.4f Ti=%.4f Target=%.0f RPM\n",
|
||||||
|
context->get_Kp(), context->get_Ti(), context->get_target_rpm());
|
||||||
|
|
||||||
#if LOG_CSV
|
#if LOG_CSV
|
||||||
printk("time_ms,ref_rpm,actual_rpm,pwm\n");
|
printk("time_ms,ref_rpm,actual_rpm,pwm\n");
|
||||||
#endif
|
#endif
|
||||||
@@ -50,7 +54,7 @@ void OperationalState::command(char c)
|
|||||||
{
|
{
|
||||||
if (c == 'r' || c == 'R')
|
if (c == 'r' || c == 'R')
|
||||||
{
|
{
|
||||||
printk("Command: reset\n");
|
printk("Command: reset communication\n"); // Heldur Kp og Ti gildum
|
||||||
|
|
||||||
context->to_initialization();
|
context->to_initialization();
|
||||||
}
|
}
|
||||||
@@ -61,6 +65,31 @@ void OperationalState::command(char c)
|
|||||||
|
|
||||||
context->to_pre_operational();
|
context->to_pre_operational();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (c == '+') // Bætti þessu við til þess að prófa að rampa rpm í operational state
|
||||||
|
{
|
||||||
|
context->set_target_rpm(context->get_target_rpm() + 10);
|
||||||
|
printk("Target: %.0f RPM\n", context->get_target_rpm());
|
||||||
|
}
|
||||||
|
else if (c == '-')
|
||||||
|
{
|
||||||
|
context->set_target_rpm(context->get_target_rpm() - 10);
|
||||||
|
printk("Target: %.0f RPM\n", context->get_target_rpm());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tímabundið til þess að testa reset parameters
|
||||||
|
else if (c == 'x' || c == 'X')
|
||||||
|
{
|
||||||
|
printk("Command: reset node\n");
|
||||||
|
context->reset_parameters();
|
||||||
|
context->to_initialization();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (c == '?')
|
||||||
|
{
|
||||||
|
printk("Actual=%.0f RPM Duty=%.1f\n",
|
||||||
|
context->get_actual_rpm(), context->get_duty_percent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "p_controller.h"
|
#include "p_controller.h"
|
||||||
|
|
||||||
P_controller::P_controller(double Kp)
|
P_controller::P_controller(double Kp)
|
||||||
: Kp(Kp)
|
: Kp(Kp),
|
||||||
|
default_Kp(Kp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11,3 +12,9 @@ double P_controller::update(double ref, double actual)
|
|||||||
|
|
||||||
return Kp * error;
|
return Kp * error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void P_controller::restore_defaults()
|
||||||
|
{
|
||||||
|
Kp = default_Kp;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|||||||
+16
-2
@@ -1,6 +1,6 @@
|
|||||||
#include "pi_controller.h"
|
#include "pi_controller.h"
|
||||||
|
|
||||||
PI_controller::PI_controller(double Kp, double Ti, double T) : P_controller(Kp), Ti(Ti), T(T), integral(0.0)
|
PI_controller::PI_controller(double Kp, double Ti, double T) : P_controller(Kp), Ti(Ti), default_Ti(Ti), T(T), integral(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,21 @@ void PI_controller::reset()
|
|||||||
integral = 0.0;
|
integral = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PI_controller::set_Ti(double value)
|
bool PI_controller::set_Ti(double value)
|
||||||
{
|
{
|
||||||
|
if (value > 0.0)
|
||||||
|
{
|
||||||
Ti = value;
|
Ti = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PI_controller::restore_defaults()
|
||||||
|
{
|
||||||
|
P_controller::restore_defaults();
|
||||||
|
Ti = default_Ti;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
#include "pre_operational_state.h"
|
#include "pre_operational_state.h"
|
||||||
#include "motor_controller.h"
|
#include "motor_controller.h"
|
||||||
|
|
||||||
#include "p_controller.h"
|
// #include "p_controller.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/sys/printk.h>
|
#include <zephyr/sys/printk.h>
|
||||||
|
|
||||||
PreOperationalState::PreOperationalState(P_controller &p_controller, P_controller &pi_controller)
|
// PreOperationalState::PreOperationalState(P_controller &p_controller, P_controller &pi_controller)
|
||||||
: p_controller(p_controller),
|
PreOperationalState::PreOperationalState()
|
||||||
pi_controller(pi_controller),
|
// : p_controller(p_controller),
|
||||||
pi_selected(true),
|
// pi_controller(pi_controller),
|
||||||
previous_time(0),
|
// pi_selected(true),
|
||||||
|
: previous_time(0),
|
||||||
led_state(false),
|
led_state(false),
|
||||||
input_mode(NONE),
|
input_mode(NONE),
|
||||||
input_index(0)
|
input_index(0)
|
||||||
@@ -23,7 +24,8 @@ void PreOperationalState::enter()
|
|||||||
printk("State: Pre-operational\n");
|
printk("State: Pre-operational\n");
|
||||||
|
|
||||||
// The selection survives a reset, so report it (used by capture_serial.py).
|
// The selection survives a reset, so report it (used by capture_serial.py).
|
||||||
printk("Controller: %s\n", pi_selected ? "PI" : "P");
|
printk("Controller: %s\n", (context->get_controller_type() == ControllerType::PI) ? "PI" : "P");
|
||||||
|
// Prófaði þetta, veit ekki hvort þetta skili bool
|
||||||
|
|
||||||
context->stop_motor();
|
context->stop_motor();
|
||||||
|
|
||||||
@@ -79,10 +81,21 @@ void PreOperationalState::command(char c)
|
|||||||
}
|
}
|
||||||
else if (input_mode == ENTER_TI)
|
else if (input_mode == ENTER_TI)
|
||||||
{
|
{
|
||||||
context->set_Ti(value);
|
if (context->set_Ti(value))
|
||||||
|
{
|
||||||
printk("Ti set to: %.4f\n", value);
|
printk("Ti set to: %.4f\n", value);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printk("Ti rejected, must be > 0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (input_mode == ENTER_RPM)
|
||||||
|
{
|
||||||
|
context->set_target_rpm(value);
|
||||||
|
|
||||||
|
printk("Target RPM set to: %.0f\n", value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finished entering a value
|
// Finished entering a value
|
||||||
@@ -138,20 +151,28 @@ void PreOperationalState::command(char c)
|
|||||||
printk("Enter Ti and press Enter:\n");
|
printk("Enter Ti and press Enter:\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (c == 'v' || c == 'V')
|
||||||
|
{
|
||||||
|
input_mode = ENTER_RPM;
|
||||||
|
input_index = 0;
|
||||||
|
|
||||||
|
printk("Enter RPM and press Enter:\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Select controller algorithm, the controller is passed to the motor controller
|
// Select controller algorithm, the controller is passed to the motor controller
|
||||||
else if (c == 'c' || c == 'C')
|
else if (c == 'c' || c == 'C')
|
||||||
{
|
{
|
||||||
pi_selected = !pi_selected;
|
if (context->get_controller_type() == ControllerType::P)
|
||||||
|
|
||||||
if (pi_selected)
|
|
||||||
{
|
{
|
||||||
context->set_controller(pi_controller);
|
context->select_controller(ControllerType::PI);
|
||||||
printk("Controller: PI\n");
|
printk("Controller: PI, Kp=%.4f, Ti=%.4f\n",
|
||||||
|
context->get_Kp(), context->get_Ti());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context->set_controller(p_controller);
|
context->select_controller(ControllerType::P);
|
||||||
printk("Controller: P\n");
|
printk("Controller: P, Kp=%.4f\n",
|
||||||
|
context->get_Kp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user