A simple PWM LED approach for the Thingy:91

I'm trying to drive the RGB LED light on the Thingy:91. So far, I've not been successful. I was hoping that by listing the steps I perform I might be able to get some advice. This is the first time that I've dealt with PWM. Here are the steps I'm presently taking:

1. Using PWM0_NS (my program is insecure), assign pins p0_29, p0_30, and p0_31 having set them up as push/pull output with an initial level of high.
2. Set the period of the PWM to 500hz.
3. I then loop around wanting to toggle the LED on and off by setting the duty of all three channels to the max duty (on) and 0 (off) with about 1 second sleep in between.

Does this approach seem reasonable? I really want the simplest PWM RGB LED demo I can; think of blinky for the RGB LED.

Thanks for any help.

Top Replies

  • Hello Christopher,

    Zephyr provides a straightforward sample showing how to control an LED with a PWM peripheral.

    You can find it in your ncs folder: ../zephyr/samples/basic/blinky_pwm.

    It doesn’t work for the Thingy:91 from scratch, but you can easily get it to work with the following modifications:

    • Create an overlay file in your application root called: thingy91_nrf9160ns.overlay
    • Add the following lines to the overlay file

    / {
        pwmleds {
            compatible = "pwm-leds";
            pwm_led0: pwm_led_0 {
                pwms = < &pwm0 0x1f >;
        aliases {
            pwm-led0 = &pwm_led0;

    • Build and run

    The application should now trigger the blue LED colour of the lightwell LED.

    I hope this is a good starting point for you!



  • Do those settings of mine also look right though (I'm not using Zephyr in my own app)

  • Hello Christopher,

    Since you are not using Zephyr in your application, I assume that you are using the pwm_nrfx drivers directly?

    I’m not quite sure if I understand point 3, though. Can you elaborate? Thanks!



  • OK, I confess. I'm using Rust. :-) I've had a lot of success using Rust with other Nordic hardware and so I'm now trying to get board support happening with the Thingy:91. By point 3, here's the code:

        rprintln!("PWM Blinky demo starting");
        loop {
            delay(&mut timer, 250_000); // 250ms
            delay(&mut timer, 1_000_000); // 1s

    And here's the setup:

    fn init_device(p: hal::pac::Peripherals) -> (Pwm<hal::pac::PWM0_NS>, Timer<hal::pac::TIMER0_NS>) {
        let p0 = gpio::p0::Parts::new(p.P0_NS);
        let pwm = Pwm::new(p.PWM0_NS);
        let timer = Timer::new(p.TIMER0_NS);
        (pwm, timer)

    The Zephyr code you referred to actually does something interesting with the max duty value. It appears as though it keeps halving it until setting the duty is accepted. Perhaps that's what I need to do here.