Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth: Mesh: Recalculate regulator internal sum #11713

Merged
merged 3 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions include/bluetooth/mesh/light_ctrl_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,22 @@ struct bt_mesh_light_ctrl_reg_cfg {

/** Common regulator context */
struct bt_mesh_light_ctrl_reg {
/** Initialize the regulator. */
/** Initialize the regulator.
*
* @param[in] reg Illuminance regulator instance.
*/
void (*init)(struct bt_mesh_light_ctrl_reg *reg);
/** Start the regulator. */
void (*start)(struct bt_mesh_light_ctrl_reg *reg);
/** Stop the regulator. */
/** Start the regulator.
*
* @param[in] reg Illuminance regulator instance.
* @param[in] lightness Current lightness level
* value equal to @c lightness.
*/
void (*start)(struct bt_mesh_light_ctrl_reg *reg, uint16_t lightness);
/** Stop the regulator.
*
* @param[in] reg Illuminance regulator instance.
*/
void (*stop)(struct bt_mesh_light_ctrl_reg *reg);
/** Regulator configuration. */
struct bt_mesh_light_ctrl_reg_cfg cfg;
Expand Down
4 changes: 3 additions & 1 deletion include/bluetooth/mesh/light_ctrl_reg_spec.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ struct bt_mesh_light_ctrl_reg_spec {
float i;
/** Regulator enabled flag. */
bool enabled;
/* If true, internal integral sum can be negative until it becomes positive. */
bool neg;
};

/** @cond INTERNAL_HIDDEN */
void bt_mesh_light_ctrl_reg_spec_init(struct bt_mesh_light_ctrl_reg *reg);
void bt_mesh_light_ctrl_reg_spec_start(struct bt_mesh_light_ctrl_reg *reg);
void bt_mesh_light_ctrl_reg_spec_start(struct bt_mesh_light_ctrl_reg *reg, uint16_t lightness);
void bt_mesh_light_ctrl_reg_spec_stop(struct bt_mesh_light_ctrl_reg *reg);
/** @endcond */

Expand Down
2 changes: 1 addition & 1 deletion include/bluetooth/mesh/light_ctrl_srv.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ struct bt_mesh_light_ctrl_srv {
struct bt_mesh_light_ctrl_reg *reg;
/** Previous regulator value */
uint16_t reg_prev;
#endif
#endif /* CONFIG_BT_MESH_LIGHT_CTRL_SRV_REG */
/** Lightness server instance */
struct bt_mesh_lightness_srv *lightness;
/** Extended Generic OnOff server */
Expand Down
74 changes: 55 additions & 19 deletions subsys/bluetooth/mesh/light_ctrl_reg_spec.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,19 @@

#define REG_INT CONFIG_BT_MESH_LIGHT_CTRL_REG_SPEC_INTERVAL

static void reg_step(struct k_work *work)
{
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
struct bt_mesh_light_ctrl_reg_spec *spec_reg = CONTAINER_OF(
dwork, struct bt_mesh_light_ctrl_reg_spec, timer);

if (!spec_reg->enabled) {
/* The regulator might be disabled asynchronously. */
return;
}

k_work_reschedule(&spec_reg->timer, K_MSEC(REG_INT));
struct reg_terms {
float i;
float p;
};

static struct reg_terms reg_terms_calc(struct bt_mesh_light_ctrl_reg_spec *spec_reg)
{
float target = bt_mesh_light_ctrl_reg_target_get(&spec_reg->reg);
float error = target - spec_reg->reg.measured;
/* Accuracy should be in percent and both up and down: */
float accuracy = (spec_reg->reg.cfg.accuracy * target) / (2 * 100.0f);
float input;
float kp, ki;

if (error > accuracy) {
input = error - accuracy;
Expand All @@ -35,8 +30,6 @@ static void reg_step(struct k_work *work)
input = 0.0f;
}

float kp, ki;

if (input >= 0) {
kp = spec_reg->reg.cfg.kp.up;
ki = spec_reg->reg.cfg.ki.up;
Expand All @@ -45,21 +38,64 @@ static void reg_step(struct k_work *work)
ki = spec_reg->reg.cfg.ki.down;
}

spec_reg->i += (input * ki) * ((float)REG_INT / (float)MSEC_PER_SEC);
spec_reg->i = CLAMP(spec_reg->i, 0, UINT16_MAX);
return (struct reg_terms){
.i = ((input) * (ki) * ((float)REG_INT / (float)MSEC_PER_SEC)),
.p = input * kp,
};
}

static void reg_step(struct k_work *work)
{
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
struct bt_mesh_light_ctrl_reg_spec *spec_reg = CONTAINER_OF(
dwork, struct bt_mesh_light_ctrl_reg_spec, timer);
struct reg_terms reg_terms;

if (!spec_reg->enabled) {
/* The regulator might be disabled asynchronously. */
return;
}

k_work_reschedule(&spec_reg->timer, K_MSEC(REG_INT));

reg_terms = reg_terms_calc(spec_reg);
spec_reg->i += reg_terms.i;

if (spec_reg->i >= 0) {
/* Drop the negative flag as soon as the internal sum becomes positive. */
spec_reg->neg = false;
}

if (!spec_reg->neg) {
spec_reg->i = CLAMP(spec_reg->i, 0, UINT16_MAX);
}

float p = input * kp;
float output = spec_reg->i + p;
float output = spec_reg->i + reg_terms.p;

spec_reg->reg.updated(&spec_reg->reg, output);
}

void bt_mesh_light_ctrl_reg_spec_start(struct bt_mesh_light_ctrl_reg *reg)
static void internal_sum_recover(struct bt_mesh_light_ctrl_reg_spec *spec_reg, uint16_t lightness)
{
struct reg_terms reg_terms;

reg_terms = reg_terms_calc(spec_reg);

/* Recalculate the internal sum so that it is equal to the passed lightness level at the
* next regulator step.
*/
spec_reg->i = lightness - reg_terms.i;
/* Allow the internal sum to be negative until it becomes positive. */
spec_reg->neg = true;
}

void bt_mesh_light_ctrl_reg_spec_start(struct bt_mesh_light_ctrl_reg *reg, uint16_t lightness)
{
struct bt_mesh_light_ctrl_reg_spec *spec_reg = CONTAINER_OF(
reg, struct bt_mesh_light_ctrl_reg_spec, reg);
spec_reg->enabled = true;
k_work_schedule(&spec_reg->timer, K_MSEC(REG_INT));
internal_sum_recover(spec_reg, lightness);
}

void bt_mesh_light_ctrl_reg_spec_stop(struct bt_mesh_light_ctrl_reg *reg)
Expand Down
39 changes: 19 additions & 20 deletions subsys/bluetooth/mesh/light_ctrl_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,6 @@ static void restart_timer(struct bt_mesh_light_ctrl_srv *srv, uint32_t delay)
k_work_reschedule(&srv->timer, K_MSEC(delay));
}

static void reg_start(struct bt_mesh_light_ctrl_srv *srv)
{
#if CONFIG_BT_MESH_LIGHT_CTRL_SRV_REG
if (srv->reg && srv->reg->start) {
srv->reg->start(srv->reg);
}
#endif
}

static void reg_stop(struct bt_mesh_light_ctrl_srv *srv)
{
#if CONFIG_BT_MESH_LIGHT_CTRL_SRV_REG
if (srv->reg && srv->reg->stop) {
srv->reg->stop(srv->reg);
}
#endif
}


static inline uint32_t to_centi_lux(const struct sensor_value *lux)
{
return lux->val1 * 100L + lux->val2 / 10000L;
Expand Down Expand Up @@ -539,6 +520,24 @@ static void ctrl_enable(struct bt_mesh_light_ctrl_srv *srv)
/* Regulator remains stopped until fresh LuxLevel is received. */
}

static void reg_start(struct bt_mesh_light_ctrl_srv *srv)
{
#if CONFIG_BT_MESH_LIGHT_CTRL_SRV_REG
if (srv->reg && srv->reg->start) {
srv->reg->start(srv->reg, to_linear(light_get(srv)));
}
#endif
}

static void reg_stop(struct bt_mesh_light_ctrl_srv *srv)
{
#if CONFIG_BT_MESH_LIGHT_CTRL_SRV_REG
if (srv->reg && srv->reg->stop) {
srv->reg->stop(srv->reg);
}
#endif
}

static void ctrl_disable(struct bt_mesh_light_ctrl_srv *srv)
{
/* Do not change the light level, disabling the control server just
Expand Down Expand Up @@ -589,7 +588,7 @@ static void timeout(struct k_work *work)
* of the transition:
*/
if (atomic_test_and_clear_bit(&srv->flags, FLAG_TRANSITION)) {
LOG_DBG("Transition complete");
LOG_DBG("Transition complete. State: %d", srv->state);

/* If the fade wasn't instant, we've already published the
* steady state in the state change function.
Expand Down
8 changes: 4 additions & 4 deletions tests/subsys/bluetooth/mesh/light_ctrl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ target_compile_options(app
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_MANUAL=5
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_OCCUPANCY_MODE=1
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_OCCUPANCY_DELAY=0
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_FADE_ON=500
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_ON=3
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_FADE_ON=1000
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_ON=60
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_FADE_PROLONG=5000
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_FADE_STANDBY_AUTO=5000
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_PROLONG=3
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_FADE_STANDBY_MANUAL=500
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_LVL_STANDBY=500
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_TIME_FADE_STANDBY_MANUAL=700
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_LVL_STANDBY=700
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_LVL_ON=20000
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_LVL_PROLONG=10000
-DCONFIG_BT_MESH_LIGHT_CTRL_SRV_REG=1
Expand Down
Loading
Loading