Skip to content

Commit 9047331

Browse files
Damian-Nordicpull[bot]
authored andcommitted
[nrfconnect] Add PWM support to the lighting-app (#4237)
* [nrfconnect] Add PWM support to lighting-app * Init level cluster
1 parent e802c30 commit 9047331

File tree

7 files changed

+72
-38
lines changed

7 files changed

+72
-38
lines changed

examples/lighting-app/nrfconnect/README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# CHIP nRF Connect Lighting Example Application
22

33
The nRF Connect Lighting Example demonstrates how to remotely control a white
4-
non-dimmable light bulb. It uses buttons to test changing the lighting and
5-
device states and LEDs to show the state of these changes. You can use this
6-
example as a reference for creating your own application.
4+
dimmable light bulb. It uses buttons to test changing the lighting and device
5+
states and LEDs to show the state of these changes. You can use this example as
6+
a reference for creating your own application.
77

88
The example is based on [CHIP](https://github.com/project-chip/connectedhomeip)
99
and the nRF Connect platform, and supports remote access and control of a

examples/lighting-app/nrfconnect/dts.overlay

+23
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,36 @@
1515
*/
1616

1717
/ {
18+
1819
/*
1920
* In some default configurations within the nRF Connect SDK,
2021
* e.g. on nRF52840, the chosen zephyr,entropy node is &cryptocell.
2122
* This devicetree overlay ensures that default is overridden wherever it
2223
* is set, as this application uses the RNG node for entropy exclusively.
2324
*/
25+
2426
chosen {
2527
zephyr,entropy = &rng;
2628
};
29+
30+
/*
31+
* By default, PWM module is only configured for led0 (LED1 on the board).
32+
* The lighting-app, however, uses LED2 to show the state of the lighting,
33+
* including its brightness level.
34+
*/
35+
aliases {
36+
pwm-led1 = &pwm_led1;
37+
};
38+
39+
pwmleds {
40+
pwm_led1: pwm_led_1 {
41+
pwms = < &pwm0 0xe >;
42+
};
43+
};
44+
45+
};
46+
47+
&pwm0 {
48+
ch1-pin = < 0xe >;
49+
ch1-inverted;
2750
};

examples/lighting-app/nrfconnect/main/AppTask.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ int AppTask::Init()
100100
k_timer_init(&sFunctionTimer, &AppTask::TimerEventHandler, nullptr);
101101
k_timer_user_data_set(&sFunctionTimer, this);
102102

103-
ret = LightingMgr().Init(LIGHTING_GPIO_DEVICE_NAME, LIGHTING_GPIO_PIN);
103+
ret = LightingMgr().Init(LIGHTING_PWM_DEVICE, LIGHTING_PWM_CHANNEL);
104104
if (ret != 0)
105105
return ret;
106106

@@ -505,13 +505,23 @@ void AppTask::DispatchEvent(AppEvent * aEvent)
505505

506506
void AppTask::UpdateClusterState()
507507
{
508-
uint8_t newValue = LightingMgr().IsTurnedOn();
508+
uint8_t onoff = LightingMgr().IsTurnedOn();
509509

510510
// write the new on/off value
511-
EmberAfStatus status = emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &newValue,
511+
EmberAfStatus status = emberAfWriteAttribute(1, ZCL_ON_OFF_CLUSTER_ID, ZCL_ON_OFF_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &onoff,
512512
ZCL_BOOLEAN_ATTRIBUTE_TYPE);
513513
if (status != EMBER_ZCL_STATUS_SUCCESS)
514514
{
515-
LOG_ERR("Updating on/off %x", status);
515+
LOG_ERR("Updating on/off cluster failed: %x", status);
516+
}
517+
518+
uint8_t level = LightingMgr().GetLevel();
519+
520+
status = emberAfWriteAttribute(1, ZCL_LEVEL_CONTROL_CLUSTER_ID, ZCL_CURRENT_LEVEL_ATTRIBUTE_ID, CLUSTER_MASK_SERVER, &level,
521+
ZCL_DATA8_ATTRIBUTE_TYPE);
522+
523+
if (status != EMBER_ZCL_STATUS_SUCCESS)
524+
{
525+
LOG_ERR("Updating level cluster failed: %x", status);
516526
}
517527
}

examples/lighting-app/nrfconnect/main/LightingManager.cpp

+20-25
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,27 @@
2121
#include "AppConfig.h"
2222
#include "LogUtils.h"
2323

24+
#include <drivers/pwm.h>
2425
#include <zephyr.h>
2526

2627
LightingManager LightingManager::sLight;
2728

28-
int LightingManager::Init(const char * gpioDeviceName, gpio_pin_t gpioPin)
29+
int LightingManager::Init(const char * pwmDeviceName, uint32_t pwmChannel)
2930
{
3031
// We use a gpioPin instead of a LEDWidget here because we want to use PWM
3132
// and other features instead of just on/off.
3233

3334
mState = kState_On;
34-
mGPIOPin = gpioPin;
35-
mGPIODevice = const_cast<device *>(device_get_binding(gpioDeviceName));
35+
mLevel = kMaxLevel;
36+
mPwmDevice = device_get_binding(pwmDeviceName);
37+
mPwmChannel = pwmChannel;
3638

37-
if (!mGPIODevice)
39+
if (!mPwmDevice)
3840
{
39-
LOG_ERR("Cannot find GPIO port %s", LOG_STRDUP(gpioDeviceName));
41+
LOG_ERR("Cannot find PWM device %s", LOG_STRDUP(pwmDeviceName));
4042
return -ENODEV;
4143
}
4244

43-
int res = gpio_pin_configure(mGPIODevice, mGPIOPin, GPIO_OUTPUT);
44-
if (res != 0)
45-
{
46-
LOG_ERR("Cannot configure GPIO pin");
47-
return res;
48-
}
49-
5045
Set(false);
5146
return 0;
5247
}
@@ -74,7 +69,7 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint8_t s
7469
action_initiated = true;
7570
new_state = kState_Off;
7671
}
77-
else if (aAction == LEVEL_ACTION)
72+
else if (aAction == LEVEL_ACTION && *value != mLevel)
7873
{
7974
action_initiated = true;
8075
if (*value == 0)
@@ -114,20 +109,20 @@ bool LightingManager::InitiateAction(Action_t aAction, int32_t aActor, uint8_t s
114109

115110
void LightingManager::SetLevel(uint8_t aLevel)
116111
{
117-
LOG_INF("LEVEL %u", aLevel);
118-
// TODO: use the level for PWM
112+
LOG_INF("Setting brightness level to %u", aLevel);
113+
mLevel = aLevel;
114+
UpdateLight();
119115
}
120116

121117
void LightingManager::Set(bool aOn)
122118
{
123-
if (aOn)
124-
{
125-
mState = kState_On;
126-
gpio_pin_set_raw(mGPIODevice, mGPIOPin, 0);
127-
}
128-
else
129-
{
130-
mState = kState_Off;
131-
gpio_pin_set_raw(mGPIODevice, mGPIOPin, 1);
132-
}
119+
mState = aOn ? kState_On : kState_Off;
120+
UpdateLight();
121+
}
122+
123+
void LightingManager::UpdateLight()
124+
{
125+
constexpr uint32_t kPwmWidthUs = 1000u;
126+
const uint8_t level = mState == kState_On ? mLevel : 0;
127+
pwm_pin_set_usec(mPwmDevice, mPwmChannel, kPwmWidthUs, kPwmWidthUs * level / kMaxLevel, 0);
133128
}

examples/lighting-app/nrfconnect/main/include/AppConfig.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
#define BLE_ADVERTISEMENT_START_BUTTON_MASK DK_BTN4_MSK
3131

3232
#define SYSTEM_STATE_LED DK_LED1 // led0 in device tree
33-
#define LIGHTING_GPIO_DEVICE_NAME DT_GPIO_LABEL(DT_ALIAS(led1), gpios)
34-
#define LIGHTING_GPIO_PIN DT_GPIO_PIN(DT_ALIAS(led1), gpios)
33+
#define LIGHTING_PWM_DEVICE DT_PWMS_LABEL(DT_ALIAS(pwm_led1))
34+
#define LIGHTING_PWM_CHANNEL DT_PWMS_CHANNEL(DT_ALIAS(pwm_led1))
3535

3636
// Time it takes in ms for the simulated actuator to move from one state to another.
3737
#define ACTUATOR_MOVEMENT_PERIOS_MS 2000

examples/lighting-app/nrfconnect/main/include/LightingManager.h

+9-4
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,27 @@ class LightingManager
4343

4444
using LightingCallback_fn = void (*)(Action_t, int32_t);
4545

46-
int Init(const char * gpioDeviceName, gpio_pin_t gpioPin);
46+
int Init(const char * pwmDeviceName, uint32_t pwmChannel);
4747
bool IsTurnedOn() const { return mState == kState_On; }
48+
uint8_t GetLevel() const { return mLevel; }
4849
bool InitiateAction(Action_t aAction, int32_t aActor, uint8_t size, uint8_t * value);
4950
void SetCallbacks(LightingCallback_fn aActionInitiated_CB, LightingCallback_fn aActionCompleted_CB);
5051

5152
private:
52-
friend LightingManager & LightingMgr(void);
53+
static constexpr uint8_t kMaxLevel = 255;
54+
55+
friend LightingManager & LightingMgr();
5356
State_t mState;
54-
gpio_pin_t mGPIOPin;
55-
device * mGPIODevice;
57+
uint8_t mLevel;
58+
const device * mPwmDevice;
59+
uint32_t mPwmChannel;
5660

5761
LightingCallback_fn mActionInitiated_CB;
5862
LightingCallback_fn mActionCompleted_CB;
5963

6064
void Set(bool aOn);
6165
void SetLevel(uint8_t aLevel);
66+
void UpdateLight();
6267

6368
static LightingManager sLight;
6469
};

examples/lighting-app/nrfconnect/prj.conf

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
# Add support for LEDs and buttons on Nordic development kits
2222
CONFIG_DK_LIBRARY=y
23+
CONFIG_PWM=y
2324

2425
# Default OpenThread network settings
2526
CONFIG_OPENTHREAD_PANID=4660

0 commit comments

Comments
 (0)