From ab818974f305b87cd398588b61aaf0d7cfe6f7fd Mon Sep 17 00:00:00 2001 From: zys Date: Fri, 20 Mar 2026 21:02:04 +0800 Subject: [PATCH] refactor: use dc-motor driver as low level layer --- boards/rpi_pico.overlay | 38 +++++------ prj.conf | 2 + src/main.cpp | 140 +++++++++++++++++++++++----------------- 3 files changed, 100 insertions(+), 80 deletions(-) diff --git a/boards/rpi_pico.overlay b/boards/rpi_pico.overlay index 1deaa72..0c631b9 100644 --- a/boards/rpi_pico.overlay +++ b/boards/rpi_pico.overlay @@ -1,25 +1,21 @@ / { - zephyr,user { - in3-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; - in4-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; - enb-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>; - }; -}; -&uart0 { - status = "okay"; - protocal: uart-com-protocal { - compatible = "uart-com-protocal"; + dc_motor: dc-motor0 { + status = "okay"; + compatible = "st,l298n"; + freq-hz = <1000>; + in1-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>; + in2-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + en-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + }; + aliases { + modbus-server-pc = &modbus_pc; + }; +}; + +&uart1 { + status = "okay"; + current-speed = <115200>; + modbus_pc: modbus-server0 { status = "okay"; - header = <0x7e 0xe7>; - crc16 = "none"; - freq{ - id = <0x00>; - }; - switch{ - id = <0x01>; - }; - status{ - id = <0x02>; - }; }; }; diff --git a/prj.conf b/prj.conf index 59e87b8..974966e 100644 --- a/prj.conf +++ b/prj.conf @@ -7,4 +7,6 @@ CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_MODBUS=y +CONFIG_MODBUS_ROLE_SERVER=y CONFIG_LOG=y \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 29c6267..5b515fe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,74 +1,96 @@ -#include -#include +#include #include +#include namespace { -enum Cmd { - kFreq = 0x00, - kSwitch = 0x01, - kStatus = 0x02, -}; -#define ZEPHYR_USER_NODE DT_PATH(zephyr_user) -const gpio_dt_spec in3 = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, in3_gpios); -const gpio_dt_spec in4 = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, in4_gpios); -const gpio_dt_spec enb = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, enb_gpios); -volatile uint8_t duty_cycle_event{50}; -volatile bool is_enable{false}; -class Motor { + +class ModbusServer { public: - Motor() { - gpio_pin_configure_dt(&in3, GPIO_OUTPUT_INACTIVE); - gpio_pin_configure_dt(&in4, GPIO_OUTPUT_INACTIVE); - gpio_pin_configure_dt(&enb, GPIO_OUTPUT_INACTIVE); + struct Addr { + enum Coil : uint16_t { MOTOR_RUNNING = 0 }; + enum Reg : uint16_t { + SPEED = 0, + }; + }; + ModbusServer() { + m_iface = + modbus_iface_get_by_name(DEVICE_DT_NAME(DT_ALIAS(modbus_server_pc))); + modbus_init_server(m_iface, m_param); } - auto Rotate() -> void { - gpio_pin_set_dt(&in3, 1); - gpio_pin_set_dt(&in4, 0); - }; - auto Reverse() { - gpio_pin_set_dt(&in3, 0); - gpio_pin_set_dt(&in4, 1); - }; - auto Stop() { - gpio_pin_set_dt(&in3, 0); - gpio_pin_set_dt(&in4, 0); +private: + static auto CoilWr(uint16_t addr, bool state) -> int { + switch (addr) { + case Addr::Coil::MOTOR_RUNNING: { + if (0 == state) { + m_motor.SetSpeed(0); + } + return 0; + } + default: + return -EINVAL; + } } + static auto CoilRd(uint16_t addr, bool *state) -> int { + switch (addr) { + case Addr::Coil::MOTOR_RUNNING: { + const auto s = m_motor.GetState(); + *state = (s == driver::DcMotorState::RUNNING); + return 0; + } + default: + return -EINVAL; + } + } + static auto RegWr(uint16_t addr, uint16_t reg) -> int { + switch (addr) { + case Addr::Reg::SPEED: { + m_current_speed = reg; + return int(m_motor.SetSpeed(reg).code_id()); + } + default: + return -EINVAL; + } + } + static auto RedRd(uint16_t addr, uint16_t *reg) -> int { + switch (addr) { + case Addr::Reg::SPEED: + *reg = m_current_speed; + return 0; + default: + return -EINVAL; + } + } + + inline static modbus_user_callbacks m_cbs = {.coil_rd = CoilRd, + .coil_wr = CoilWr, + .holding_reg_rd = RedRd, + .holding_reg_wr = RegWr}; + inline static modbus_iface_param m_param = { + .mode = MODBUS_MODE_RTU, + .server = + { + .user_cb = &m_cbs, + .unit_id = 1, + }, + .serial = + { + .baud = + DT_PROP(DT_PARENT(DT_ALIAS(modbus_server_pc)), current_speed), + + .parity = UART_CFG_PARITY_NONE, + }, + }; + inline static int m_iface; + inline static int m_current_speed{0}; + inline static auto &m_motor = + ZPP_DRV_GET(driver::DcMotor, DT_NODELABEL(dc_motor)); }; -Motor motor{}; } // namespace auto main(void) -> int { - auto &protocal = ZPP_DRV_GET(uart_com::Protocal, DT_NODELABEL(protocal)); - protocal.SetRxCallback(kSwitch, [](uart_com::DataType data) { - if (data[0] == 0) { - motor.Stop(); - } else { - motor.Rotate(); - } - - printk("set switch: %d\n", data[0]); - is_enable = data[0]; - }); - protocal.SetRxCallback(kFreq, [](uart_com::DataType data) { - printk("set freq: %d\n", data[0]); - - uint8_t freq = 0; - if (data[0] == 100) { - freq = 100; - } - freq = data[0]; - duty_cycle_event = freq; - }); - + ModbusServer server{}; while (1) { - if (is_enable) { - printk("duty circle %d\n", duty_cycle_event); - gpio_pin_set_dt(&enb, 1); - k_sleep(K_MSEC(duty_cycle_event)); - gpio_pin_set_dt(&enb, 0); - k_sleep(K_MSEC(100 - duty_cycle_event)); - } } return 0; }