This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to flash the leds with a duty cycle that does not equal 50%?

Hello,

I use the nrf5340 pdk. I would like to flash the led1 with a duty cycle which is different from 50%, so i tried to open the binky_pwm project, but the segger shows that there is error.

So, I look on the forum and I find that there are people who have encountered the same problem and it has solved it well. So I follow the same steps, but it's still wrong for me. (ps: https://devzone.nordicsemi.com/f/nordic-q-a/71402/i-am-looking-for-simple-example-of-hw-driver-of-qdec-for-nrf5340)

So I would like to ask if you have any ideas on this?

Or can you give me a simpler example to achieve my goal? (for example: time on equals 2ms and time off equals 1ms.)

Thank you in advance!

  • Hello,

    I'm sorry to disturb you again.


    I want to make the four external leds have the same period and same dutu cycle which equal 25%. It means that these four leds should to be on one after another, the previous one will go out when the next one is on.


    I tried to write such code:

    #define PWM_LEDEXT1_NODE	DT_ALIAS(pwm_ledext1)
    #define PWM_LEDEXT2_NODE	DT_ALIAS(pwm_ledext2)
    #define PWM_LEDEXT3_NODE	DT_ALIAS(pwm_ledext3)
    #define PWM_LEDEXT4_NODE	DT_ALIAS(pwm_ledext4)
    
    #if DT_NODE_HAS_STATUS(PWM_LEDEXT1_NODE, okay)
    #define PWM_LABELEXT1	DT_PWMS_LABEL(PWM_LEDEXT1_NODE)
    #define PWM_CHANNELEXT1	DT_PWMS_CHANNEL(PWM_LEDEXT1_NODE)
    #define PWM_FLAGSEXT1	DT_PWMS_FLAGS(PWM_LEDEXT1_NODE)
    #else
    #error "Unsupported board: pwm-ledext1 devicetree alias is not defined"
    #define PWM_LABELEXT1	""
    #define PWM_CHANNELEXT1	0
    #define PWM_FLAGSEXT1	0
    #endif
    
    #if DT_NODE_HAS_STATUS(PWM_LEDEXT2_NODE, okay)
    #define PWM_LABELEXT2	DT_PWMS_LABEL(PWM_LEDEXT2_NODE)
    #define PWM_CHANNELEXT2	DT_PWMS_CHANNEL(PWM_LEDEXT2_NODE)
    #define PWM_FLAGSEXT2	DT_PWMS_FLAGS(PWM_LEDEXT2_NODE)
    #else
    #error "Unsupported board: pwm-ledet2 devicetree alias is not defined"
    #define PWM_LABELEXT2	""
    #define PWM_CHANNELEXT2	0
    #define PWM_FLAGSEXT2	0
    #endif
    
    #if DT_NODE_HAS_STATUS(PWM_LEDEXT3_NODE, okay)
    #define PWM_LABELEXT3	DT_PWMS_LABEL(PWM_LEDEXT3_NODE)
    #define PWM_CHANNELEXT3	DT_PWMS_CHANNEL(PWM_LEDEXT3_NODE)
    #define PWM_FLAGSEXT3	DT_PWMS_FLAGS(PWM_LEDEXT3_NODE)
    #else
    #error "Unsupported board: pwm-ledext3 devicetree alias is not defined"
    #define PWM_LABELEXT3	""
    #define PWM_CHANNELEXT3	0
    #define PWM_FLAGSEXT3	0
    #endif
    
    #if DT_NODE_HAS_STATUS(PWM_LEDEXT4_NODE, okay)
    #define PWM_LABELEXT4	DT_PWMS_LABEL(PWM_LEDEXT4_NODE)
    #define PWM_CHANNELEXT4	DT_PWMS_CHANNEL(PWM_LEDEXT4_NODE)
    #define PWM_FLAGSEXT4	DT_PWMS_FLAGS(PWM_LEDEXT4_NODE)
    #else
    #error "Unsupported board: pwm-ledext4 devicetree alias is not defined"
    #define PWM_LABELEXT4	""
    #define PWM_CHANNELEXT4	0
    #define PWM_FLAGSEXT4	0
    #endif
    
    
    #define PERIOD_USEC	(USEC_PER_SEC/5U)
    #define PULSE_WIDTH	(PERIOD_USEC/4U)
    
    
    enum { LEDEXT1, LEDEXT2, LEDEXT3, LEDEXT4 };
    
    void main(void)
    {
    	const struct device *pwm_dev[4];
            int ret1, ret2, ret3, ret4;
    
    	printk("PWM-based blinky\n");
    
            pwm_dev[LEDEXT1] = device_get_binding(PWM_LABELEXT1);
            pwm_dev[LEDEXT2] = device_get_binding(PWM_LABELEXT2);
            pwm_dev[LEDEXT3] = device_get_binding(PWM_LABELEXT3);
            pwm_dev[LEDEXT4] = device_get_binding(PWM_LABELEXT4);
    
    
            if (!pwm_dev[LEDEXT1] || !pwm_dev[LEDEXT2] || !pwm_dev[LEDEXT3] || !pwm_dev[LEDEXT4] ) {
                    printk("Error: cannot find one or more PWM devices\n");
    		return;
    	}
            
            printk("Calibrating for device %s channel %d...\n", PWM_LABELEXT1, PWM_CHANNELEXT1);
            printk("Calibrating for device %s channel %d...\n", PWM_LABELEXT2, PWM_CHANNELEXT2);
            printk("Calibrating for device %s channel %d...\n", PWM_LABELEXT3, PWM_CHANNELEXT3);
            printk("Calibrating for device %s channel %d...\n", PWM_LABELEXT4, PWM_CHANNELEXT4);
    
    
    	while (1) {
                    ret1 = pwm_pin_set_usec(pwm_dev[LEDEXT1], PWM_CHANNELEXT1, PERIOD_USEC, PULSE_WIDTH, PWM_FLAGSEXT1);
                    if (ret1 != 0) {
                            printk("Error %d: led externe 1 write failed\n", ret1);
                            return;
                    }
    
                    k_sleep(K_MSEC(50));
    
                    ret1 = pwm_pin_set_usec(pwm_dev[LEDEXT1], PWM_CHANNELEXT1, PERIOD_USEC, 0, PWM_FLAGSEXT1);
                    if (ret1 != 0) {
                            printk("Error %d: led externe 1 write failed\n", ret1);
                            return;
                    }
    
                            
                    ret2 = pwm_pin_set_usec(pwm_dev[LEDEXT2], PWM_CHANNELEXT2, PERIOD_USEC, PULSE_WIDTH, PWM_FLAGSEXT2);
                    if (ret2 != 0) {
                            printk("Error %d: led externe 2 write failed\n", ret2);
                            return;
                    }
    
                    k_sleep(K_MSEC(50));
    
                    ret2 = pwm_pin_set_usec(pwm_dev[LEDEXT2], PWM_CHANNELEXT2, PERIOD_USEC, 0, PWM_FLAGSEXT2);
                    if (ret2 != 0) {
                            printk("Error %d: led externe 2 write failed\n", ret2);
                            return;
                    }
    
                                    
                    ret3 = pwm_pin_set_usec(pwm_dev[LEDEXT3], PWM_CHANNELEXT3, PERIOD_USEC, PULSE_WIDTH, PWM_FLAGSEXT3);
                    if (ret3 != 0) {
                            printk("Error %d: led externe 3 write failed\n", ret3);
                            return;
                    }
    
                    k_sleep(K_MSEC(50));
    
                    ret3 = pwm_pin_set_usec(pwm_dev[LEDEXT3], PWM_CHANNELEXT3, PERIOD_USEC, 0, PWM_FLAGSEXT3);
                    if (ret3 != 0) {
                            printk("Error %d: led externe 3 write failed\n", ret3);
                            return;
                    }
    
                                            
                    ret4 = pwm_pin_set_usec(pwm_dev[LEDEXT4], PWM_CHANNELEXT4, PERIOD_USEC, PULSE_WIDTH, PWM_FLAGSEXT4);
                    if (ret4 != 0) {
                            printk("Error %d: led externe 4 write failed\n", ret4);
                            return;
                    }
    
                    k_sleep(K_MSEC(50));
    
                    ret4 = pwm_pin_set_usec(pwm_dev[LEDEXT4], PWM_CHANNELEXT4, PERIOD_USEC, 0, PWM_FLAGSEXT4);
                    if (ret4 != 0) {
                            printk("Error %d: led externe 4 write failed\n", ret4);
                            return;
                    }
            }
     }

    But I didn’t get the result I wanted. The picture below  show the result that I obtened.


    But what I want is the following picture:


    Do you have any idea?


    thank you in advanced!

  • Hi again,

    Try using PWM sequences for this. They will let you set up how the PWM should behave over multiple periods, and have different behavior for each channel and for each period, all on a single PWM. You can for example, using a 250ms period, set PWM0, ch0 (LED1) to 4 periods at 100%, followed by 12 periods at 0%, and PWM0, ch1 (LED2) to 4 periods at 0%, 4 periods at 100%, 8 periods at 0% etc.

    I believe the functions in these two files will be useful:

    https://github.com/nrfconnect/sdk-hal_nordic/blob/master/nrfx/drivers/include/nrfx_pwm.h

    https://github.com/nrfconnect/sdk-hal_nordic/blob/master/nrfx/drivers/src/nrfx_pwm.c

    I am looking into the easiest way to access this functionality now, and I will get back to you.

  • I have ported a demo from the nRF5 SDK to NCS v1.4.2, and modified it to the behavior you are looking for.

    4130.blinky_pwm_test.zip

    You can probably clean it up a lot, but it seems to work.

Related