pwm_fade.c

nRF52840-MDK (boards.json id: nrf52840-mdk) · File : pwm_fade.c · Language : C · Use case : Faire respirer une LED avec un canal PWM

The nRF52840 hardware PWM produces the breathing effect with no CPU involvement: a two-value sequence replayed 40 times per brightness step. LED P0.06 fades smoothly at an inaudible 25 kHz.

Hardware

An nRF52840-MDK board (Nordic nRF52840, Cortex-M4F @ 64 MHz, 1 MB flash / 256 KB RAM, BLE 5 + 802.15.4) with onboard debugger, programmed in C with nRF5 SDK v17 and the S140 SoftDevice. LED on P0.06 (onboard) + 330 Ω resistor for an external LED.

Wiring

LED anode to P0.06 through 330 Ω, cathode to GND; the output is inverted so the high level turns it off correctly depending on wiring.

How it works

NRFX_PWM generates period and duty cycle in hardware; simple_playback replays the sequence repeat times, the CPU only steps the ramp every 30 ms.

Running it

Open the matching nRF5 SDK v17 example (custom_board target), paste this code into main.c, build with Segger Embedded Studio or the gcc Makefile, then flash through the onboard debugger.

Variants

Drive the ramp from the PWM END interrupt for delay-free fading, or drive 4 channels (LED strip) with the 4 PWM sub-channels.

pwm_fade.c

// nRF52840-MDK : respiration LED sur P0.06 via le périphérique PWM0, canal 0.
// Le PWM matériel génère le signal seul : le CPU peut dormir entre deux pas.
#include "nrfx_pwm.h"
#include "nrf_delay.h"

static uint16_t seq_haute[2] = { 0, 600 };    // OFF puis ON (PWM inversé)
static uint16_t seq_basse[2] = { 600, 0 };

static void pwm_evt(nrf_pwm_event_t evt) { (void)evt; }

static void fade(bool montant) {
  nrf_pwm_values_common_t *seq = montant ? seq_basse : seq_haute;
  nrf_pwm_sequence_t s = {
    .values.p_common = seq, .length = 2,
    .repeat = 39,                              // 40 périodes = rampe douce
    .end_delay = 0,
  };
  nrf_pwm_sequence_t *seqs[] = { &s };
  nrfx_pwm_simple_playback(seqs, 1, 1, 0);
}

int main(void) {
  nrfx_pwm_config_t cfg = NRFX_PWM_DEFAULT_CONFIG(
      6, NRF_PWM_PIN_INVERTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED);
  cfg.refresh_cycle_time = 39;                 // ~40 µs -> 25 kHz inaudible
  nrfx_pwm_init(&cfg, pwm_evt);

  for (;;) {
    for (int i = 0; i < 40; i++) { fade(true);  nrf_delay_ms(30); }
    for (int i = 0; i < 40; i++) { fade(false); nrf_delay_ms(30); }
    nrf_delay_ms(400);
  }
}

← Back to the board