Simple PWM example

Hi,

Is it possible to have a simple example of using PWM with the Zephyr?

With nRF5_SDK_17.1.0 I did this:

void Pwm1Init(void)
{
    ret_code_t err_code;

    nrf_pwm_sequence_t const    m_seq =
    {
        .values.p_individual = &pwm1Values,
        .length              = NRF_PWM_VALUES_LENGTH(pwm1Values),
        .repeats             = 0,
        .end_delay           = 0
    };

    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            BUZZER_PIN | NRF_DRV_PWM_PIN_INVERTED,
	    LED_R | NRF_DRV_PWM_PIN_INVERTED,
	    LED_G | NRF_DRV_PWM_PIN_INVERTED,
	    LED_B | NRF_DRV_PWM_PIN_INVERTED,
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_250kHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = 62,                      // PWM period 4032Hz, 62 -> Duty Cycle = 100%.
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };

    err_code = nrf_drv_pwm_init(&m_pwm1, &config0, NULL);
    APP_ERROR_CHECK(err_code);

    pwm1Values.channel_0 = 0x8000;
    pwm1Values.channel_1 = 0x8000;
    pwm1Values.channel_2 = 0x8000;
    pwm1Values.channel_3 = 0x8000;

    nrf_drv_pwm_simple_playback(&m_pwm1, &m_seq, 1, NRF_DRV_PWM_FLAG_LOOP);
}

void Pwm1SetDutyCycle(uint8_t channel, uint16_t value)
{
    ((uint16_t *)(&pwm1Values))[channel] = (value | 0x8000);
}

I used the Pwm1SetDutyCycle function to set the Duty cycle of the 4 channels.
Now what do I do with the Zephyr? Can anyone give me an example? The examples I found didn't help me.

Thank you.

Parents
  • Hi,

    In lesson 4 in https://academy.nordicsemi.com/courses/nrf-connect-sdk-intermediate/ we have a course showcasing how to use the PWM API in Zephyr through nRF Connect SDK. I recommend that you have a look at this. The solution to the hands on in this lesson can be seen in github.com/.../lesson4.

    Kind regards,
    Andreas

  • Thank you,
    these lessons are very useful.
    However, I notice that there is a lesson missing that deals with the TWI module.
    I was still able to communicate via the I2C BUS but I can't set the clock frequency. In particular I want to set a frequency of 10 kHz but I don't know how.

    I tried to do like this:

    &i2c0 {
    	status = "okay";
    	pinctrl-0 = <&i2c0_default>;
    	pinctrl-names = "default";
    	clock-frequency = <10000>;
    };

    But it gives me the following error:

    C:/ncs/v2.6.0-rc2/zephyr/include/zephyr/toolchain/gcc.h:87:36: error: static assertion failed: "Wrong I2C 0 frequency setting in dts"

    Can you help me?

    Thank you

  • HI,
    I didn't understand how this solves my problem.
    I2C_BITRATE_FAST corresponds to a frequency of 400 Kbit/s as specified in the i2c.h file:

    #define I2C_BITRATE_STANDARD	100000	/* 100 Kbit/s */
    #define I2C_BITRATE_FAST	400000	/* 400 Kbit/s */        <--------
    #define I2C_BITRATE_FAST_PLUS	1000000 /* 1 Mbit/s */
    #define I2C_BITRATE_HIGH	3400000	/* 3.4 Mbit/s */
    #define I2C_BITRATE_ULTRA	5000000 /* 5 Mbit/s */

    I need to go at a slower speed. I need a speed of 10 Kbit/s.

    With nRF SDK I was able to do this by setting "frequency = 0x00290000UL".

    void ext_twi_init(void)
    {
        ret_code_t err_code;
    
        const nrf_drv_twi_config_t twi_config = {
           .scl                = EXT_SCL_PIN,
           .sda                = EXT_SDA_PIN,
           .frequency          = 0x00290000UL,      // = 10Kbit/s. <------------
           .interrupt_priority = APP_IRQ_PRIORITY_HIGH,
           .clear_bus_init     = false
        };
    
        err_code = nrf_drv_twi_init(&m_ext_twi, &twi_config, NULL, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_twi_enable(&m_ext_twi);
    }

    How do I do the same thing using Zephyr?

    Thank you

  • Maybe try setting in i2c.h the following 


    #define I2C_BITRATE_10KHZ 10000 //your custom freq value

    Then set


    &i2c0 {
    status = "okay";
    pinctrl-0 = <&i2c0_default>;
    pinctrl-names = "default";
    clock-frequency = <I2C_BITRATE_10KHZ>;
    };

    See if that helps incase the device tree and  I2C driver is only able to set frequency values defined in the i2c.h which zephyr looks for.

  • Hi,

    Thanks for the reply but it still gives me the same error:

    #define I2C_BITRATE_10KHZ 10000
    #define I2C_BITRATE_STANDARD	100000	/* 100 Kbit/s */
    #define I2C_BITRATE_FAST	400000	/* 400 Kbit/s */
    #define I2C_BITRATE_FAST_PLUS	1000000 /* 1 Mbit/s */
    #define I2C_BITRATE_HIGH	3400000	/* 3.4 Mbit/s */
    #define I2C_BITRATE_ULTRA	5000000 /* 5 Mbit/s */


    &i2c0 {
    	status = "okay";
    	pinctrl-0 = <&i2c0_default>;
    	pinctrl-names = "default";
    	clock-frequency = <I2C_BITRATE_10KHZ>;
    };


    static assertion failed: "Wrong I2C 0 frequency setting in dts"

    Do you have any other suggestions?
    Thank you.

  • hmm then this is concerning.  Lemme try on my end and see what works. Else. hopefully Nordic tech team can suggest a solution.

  • Hi Andreas,

    do you have a solution to my problem?
    Thank you
    Best regards

Reply Children
Related