Skip to content

Commit

Permalink
[refactor] initial version for bnct
Browse files Browse the repository at this point in the history
  • Loading branch information
ufan committed Apr 24, 2024
1 parent 32c165b commit 372ae16
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 57 deletions.
1 change: 1 addition & 0 deletions bnct-app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ target_sources(app PRIVATE
)

target_sources_ifdef(CONFIG_BME280 app PRIVATE src/bmp280.c)
target_sources_ifdef(CONFIG_MFC_ACU20FD app PRIVATE src/mfc_acu20fd.c)
2 changes: 1 addition & 1 deletion bnct-app/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CONFIG_UART_CONSOLE=n
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y

CONFIG_LOG=y
# CONFIG_LOG=y
CONFIG_PRINTK=y

CONFIG_SERIAL=y
Expand Down
8 changes: 4 additions & 4 deletions bnct-app/src/bmp280.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ static void bmp280_poll() {

// [todo] value interpretation to be confirmed
sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
holding_reg[REG_TEMPERATURE_INT]->value = temp.val1 & BIT_MASK(16);
holding_reg[REG_TEMPERATURE_FLT]->value = temp.val2 & BIT_MASK(16); // = flt/1000000
holding_reg[REG_TEMPERATURE_DEC]->value = temp.val1 & BIT_MASK(16);
holding_reg[REG_TEMPERATURE_FRA]->value = temp.val2 & BIT_MASK(16); // = flt/1000000

sensor_channel_get(dev, SENSOR_CHAN_PRESS, &pressure);
holding_reg[REG_PRESSURE_INT]->value = pressure.val1 & BIT_MASK(16);
holding_reg[REG_PRESSURE_FLT]->value = pressure.val2 & BIT_MASK(16); // = flt/1000000
holding_reg[REG_PRESSURE_DEC]->value = pressure.val1 & BIT_MASK(16);
holding_reg[REG_PRESSURE_FRA]->value = pressure.val2 & BIT_MASK(16); // = flt/1000000

return;
}
Expand Down
112 changes: 110 additions & 2 deletions bnct-app/src/mfc_acu20fd.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,111 @@
#ifdef CONFIG_MFC_ACU20FD

#endif // CONFIG_MFC_ACU20FD
#include "common.h"
#include <gasflow/acu20fd.h>

#include <zephyr/kernel.h>
#include <zephyr/modbus/modbus.h>

// modbus commuinication rx timeout (us)
#define MBC_RX_TIMEOUT 500000
#define ACU20FD_UINIT_ID 1
// [todo] correct data format?
#define ACU20FD_DEFAULT_PV 40

// modbus interface handle
static int mbc_iface;
static const uint8_t mbc_uid = ACU20FD_UINIT_ID;

/* poll pv */
static void mfc_acu20fd_poll() {
uint16_t buf[2];
if (!acu20fd_get_pv(mbc_iface, mbc_uid, buf)) {
holding_reg[REG_MFC_RATE_PV]->value = buf[0];
holding_reg[REG_MFC_RATE_PV + 1]->value = buf[1];
}
return;
}

POLL_HANDLER_DEFINE(acu20fd_poll, mfc_acu20fd_poll);

/* set pv */
static void mfc_acu20fd_holding_handler(uint8_t addr) {
if (addr == REG_MFC_RATE_SV && coil_reg[COIL_ONOFF_MFC]->value) {
uint16_t buf[2] = {holding_reg[REG_MFC_RATE_SV]->value,
holding_reg[REG_MFC_RATE_SV + 1]->value};

acu20fd_set_pv(mbc_iface, mbc_uid, buf);
}
return;
}

HOLDING_REG_HANDLER_DEFINE(acu20fd_holding, mfc_acu20fd_holding_handler);

/* turn on/off mfc */
static void mfc_acu20fd_coil_handler(uint8_t addr) {

switch (addr) {
case COIL_ONOFF_MFC:
uint16_t buf[2] = {holding_reg[REG_MFC_RATE_SV]->value,
holding_reg[REG_MFC_RATE_SV + 1]->value};
acu20fd_set_pv(mbc_iface, mbc_uid, buf);
break;
case COIL_DEFAULT_SPEED_MFC:
holding_reg[REG_MFC_RATE_SV]->value =
holding_reg[REG_MFC_RATE_DEFAULT]->value;
holding_reg[REG_MFC_RATE_SV + 1]->value =
holding_reg[REG_MFC_RATE_DEFAULT + 1]->value;
break;
default:
break;
}

return;
}

COIL_REG_HANDLER_DEFINE(acu20fd_coil, mfc_acu20fd_coil_handler);

/* modus interface to acu20fd (a client) */
const static struct modbus_iface_param mbc_param = {
.mode = MODBUS_MODE_RTU,
.rx_timeout = MBC_RX_TIMEOUT,
.serial = {.baud = 115200,
.parity = UART_CFG_PARITY_NONE,
.stop_bits_client = UART_CFG_STOP_BITS_1}};

#define MODBUS_CLIENT_NODE DT_ALIAS(modbus_client)

static int mbc_init(void) {
char const iface_name[] = {DEVICE_DT_NAME(MODBUS_CLIENT_NODE)};

mbc_iface = modbus_iface_get_by_name(iface_name);
if (mbc_iface < 0) {
printk("Failed to get iface index for %s\n", iface_name);
return mbc_iface;
}

return modbus_init_client(mbc_iface, mbc_param);
}

//
static int mfc_acu20fd_init(void) {

int err = mbc_init();
if (err < 0) {
printk("Modbus RTU client initialization failed\n");
return err;
}

err = acu20fd_init(mbc_iface, mbc_uid, true);
if (err < 0) {
printk("Setting ACU20FD digit mode failed\n");
return err;
}

// [todo]
/* holding_reg[REG_MFC_RATE_SV]->value = ; */
/* holding_reg[REG_MFC_RATE_DEFAULT]->value = ; */

return 0;
}

SYS_INIT(mfc_acu20fd_init, POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY);
2 changes: 1 addition & 1 deletion bnct-app/src/modbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static int holding_reg_wr(uint16_t addr, uint16_t reg) {
return 0;
}

if (addr == REG_PUMP_SPEED &&
if (addr == REG_PUMP_SPEED_SV &&
(reg < holding_reg[REG_PUMP_SPEED_MIN]->value ||
reg > holding_reg[REG_PUMP_SPEED_MAX]->value))
return -ENOTSUP;
Expand Down
68 changes: 30 additions & 38 deletions bnct-app/src/modbus_ifc.h
Original file line number Diff line number Diff line change
@@ -1,64 +1,56 @@
#pragma once


/*** holding registers ***/

/// status registers

#define REG_PV_MFC 0
#define REG_PV_PUMPSPEED 1
#define REG_PV_PRESSURE 2
#define REG_PV_TEMPERATURE 3
// MFC rate in flow-state (2 words)
// default rate is read-only
#define REG_MFC_RATE_SV 0
#define REG_MFC_RATE_DEFAULT 2
#define REG_MFC_RATE_PV 4

// voltage present value (V)
#define REG_SV_MFC 4
#define REG_SV_PUMPSPEED 5

// status polling interval (in ms)
#define REG_UPDATE_INTERVAL 6

// system alive time (high-16 bits & low-16 bits)
/// alive-time = polling-times * update_interval
#define REG_HEARTBEAT_LW 7
#define REG_HEARTBEAT_HI 8
// pump speed in recycle-state (1 word, unit: permil of full-speed)
// default speed is read-only
#define REG_PUMP_SPEED_SV 6
#define REG_PUMP_SPEED_DEFAULT 7
#define REG_PUMP_SPEED_PV 8
#define REG_PUMP_SPEED_MIN 9
#define REG_PUMP_SPEED_MAX 10

// others
#define REG_TEMPERATURE_INT 9
#define REG_TEMPERATURE_FLT 10
#define REG_PRESSURE_INT 11
#define REG_PRESSURE_FLT 12
#define REG_TEMPERATURE_DEC 11
#define REG_TEMPERATURE_FRA 12
#define REG_PRESSURE_DEC 13
#define REG_PRESSURE_FRA 14

// working modes, valid values:
// - 1 -> flow-mode,
// - 2 -> recycle-mode
// - 3 -> mix-mode (auto switching between flow & recycle)
#define REG_SET_MODE 13
#define REG_CUR_MODE 14
#define REG_CUR_STATE 15

#define REG_SET_MODE 15
#define REG_CUR_MODE 16
#define REG_CUR_STATE 17
// duration of flow & recycle state in mix-mode (unit:s)
#define REG_FLOW_DURATION 16
#define REG_RECYCLE_DURATION 17
#define REG_FLOW_DURATION 18
#define REG_RECYCLE_DURATION 19

// pump speed in recycle-state (unit: permil of full-speed)
// default speed is read-only
#define REG_PUMP_SPEED 18
#define REG_PUMP_SPEED_DEFAULT 19
#define REG_PUMP_SPEED_MIN 20
#define REG_PUMP_SPEED_MAX 21
// status polling interval (in ms)
#define REG_UPDATE_INTERVAL 20

#define REG_END 22
// system alive time (high-16 bits & low-16 bits)
#define REG_HEARTBEAT_LW 21
#define REG_HEARTBEAT_HI 22

#define REG_END 23

/*** coils ***/

/// control command coils
/// control command
#define COIL_ONOFF_MFC 0
#define COIL_ONOFF_PUMP 1
#define COIL_ONOFF_VALVE 2

/// reset command
#define COIL_DEFAULT_SPEED_PUMP 3
#define COIL_DEFAULT_SPEED_MFC 4

/* #define COIL_AUTOMATIC 4 */

#define COIL_END 5
18 changes: 10 additions & 8 deletions bnct-app/src/pump.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ static const uint32_t min_speed = DT_PROP(PUMP_NODE, min_pulse) / step; // < mi
static const uint32_t max_speed = DT_PROP(PUMP_NODE, max_pulse) / step;
static const uint32_t default_speed = DT_PROP(PUMP_NODE, default_speed); // unit: permil, i.e. 1/1000

//
// [todo] poll handler (present speed: REG_PUMP_SPEED_PV)

// coil handler
static void pump_coil_register_handler(uint8_t addr) {

switch (addr) {
case COIL_ONOFF_PUMP:
pwm_set_pulse_dt(&pump, coil_reg[COIL_ONOFF_PUMP]->value
? holding_reg[REG_PUMP_SPEED]->value * step
? holding_reg[REG_PUMP_SPEED_SV]->value * step
: 0);
break;
case COIL_DEFAULT_SPEED_PUMP:
holding_reg[REG_PUMP_SPEED]->value = default_speed;
holding_reg[REG_PUMP_SPEED_SV]->value = default_speed;
break;
default:
break;
Expand All @@ -38,24 +40,24 @@ static void pump_coil_register_handler(uint8_t addr) {

COIL_REG_HANDLER_DEFINE(pump_coil_reg, pump_coil_register_handler);

//
// holding register handler
static void pump_holding_register_handler(uint8_t addr) {
if (addr == REG_PUMP_SPEED && coil_reg[COIL_ONOFF_PUMP]->value) {
pwm_set_pulse_dt(&pump, holding_reg[REG_PUMP_SPEED]->value * step);
if (addr == REG_PUMP_SPEED_SV && coil_reg[COIL_ONOFF_PUMP]->value) {
pwm_set_pulse_dt(&pump, holding_reg[REG_PUMP_SPEED_SV]->value * step);
}
return;
}

HOLDING_REG_HANDLER_DEFINE(pump_holding_reg, pump_holding_register_handler);

//
// init
static int pump_init(void) {
if (!pwm_is_ready_dt(&pump)) {
printk("The pump is not ready.\n");
return -ENOENT;
}

holding_reg[REG_PUMP_SPEED]->value = default_speed;
holding_reg[REG_PUMP_SPEED_SV]->value = default_speed;
holding_reg[REG_PUMP_SPEED_DEFAULT]->value = default_speed;
holding_reg[REG_PUMP_SPEED_MIN]->value = min_speed;
holding_reg[REG_PUMP_SPEED_MAX]->value = max_speed;
Expand Down
2 changes: 1 addition & 1 deletion include/gasflow/acu20fd.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#pragma once

int acu20fd_init_digit_mode(const int iface);
int acu20fd_init(const int iface, const uint8_t uid, bool digit_mode);
int acu20fd_set_pv(const int iface, const uint8_t uid, uint16_t *p_pv);
int acu20fd_get_pv(const int iface, const uint8_t uid, uint16_t *p_pv);
7 changes: 5 additions & 2 deletions lib/acu20fd.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ static uint16_t __attribute__((unused)) acu20fd_cancel_zero[] = {0x3F80, 0x0000}

#define ACU20FD_DEAD_TIME_MS 200

/* set digit mode */
int acu20fd_init_digit_mode(const int iface, const uint8_t uid) {
/* set work mode: analog (digit_mode: false), digi (digit_mode: true) */
int acu20fd_init(const int iface, const uint8_t uid, bool digit_mode) {

if (!digit_mode) return 0;

int err = modbus_write_holding_regs(iface, uid, ACU20FD_REG_SET_MODE,
acu20fd_digit_mode,
ARRAY_SIZE(acu20fd_digit_mode));
Expand Down

0 comments on commit 372ae16

Please sign in to comment.