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

Making 4 regular PWM signal.

Hello, guys. I'm using the PCA10040 and the SDK 16.0's BLE UART peripheral example. I am trying to make PWM signal below.

When PWM0 stops, PWM2 works, and when PWM2 stops, then PWM3, and in the same way, PWM4 works. And this signal is constantly repeated.

I tried to implement it only with the PWM SDK example, but I thought I needed other things to make it works, so I asked a question. please give me an advise.

 

Thank you for reding my issue.

  • The simplest may be to use the nRF52833 and nRF52840 which have 4 PWM peripherals. You would need to configure all 4 PWM, and then delay the START for each of them with 200us, then they should produce the signal you show. That should be pretty straight forward I believe. 

    Please also see:
    https://infocenter.nordicsemi.com/topic/ps_nrf52833/pwm.html 

    Kenneth

  • Thank you for answer.
    Is nRF52832 impossible to do that?

    Here my code is

    app_pwm_config_t PWM_1_cfg = APP_PWM_DEFAULT_CONFIG_2CH(800L, 22, 23); // 0.8ms
    app_pwm_config_t PWM_2_cfg = APP_PWM_DEFAULT_CONFIG_2CH(800L, 24, 25); // 0.8ms

    g_s_bReadyFlag = false;
    while (app_pwm_channel_duty_set(&PWM_1, 0, 25) == NRF_ERROR_BUSY);
    while (!g_s_bReadyFlag);

    nrf_delay_us(200);
    g_s_bReadyFlag = false;
    while (app_pwm_channel_duty_set(&PWM_1, 1, 25) == NRF_ERROR_BUSY);
    while (!g_s_bReadyFlag);
    nrf_delay_us(200);

    g_s_bReadyFlag_2 = false;
    while (app_pwm_channel_duty_set(&PWM_2, 0, 25) == NRF_ERROR_BUSY);
    while (!g_s_bReadyFlag_2);
    nrf_delay_us(200);

    g_s_bReadyFlag_2 = false;
    while (app_pwm_channel_duty_set(&PWM_2, 1, 25) == NRF_ERROR_BUSY);
    while (!g_s_bReadyFlag_2);
    nrf_delay_us(200);
    If irun this code and check the scope, i can see that the 200 microsecond delay is not applied and almost the same output.
    The results were similar even when outputting separately one by one without controlling the two channels as a bundle.








  • Hi,

    I believe you can do this with four channels of a single PWM instance. Configure PWM with DECODER.LOAD=Single and create a four-step sequence, each step has zero compare value and POLARITY set for an active output:

    uint16_t pwmseq[16] = { 0x8000,0,0,0,  0,0x8000,0,0,  0,0,0x8000,0,  0,0,0,0x8000 };

    (I'm working with PWM peripheral directly rather than via app_pwm library, so I can't show a code sample with app_pwm)

  • Hello Dmitry.

    First, thant you for answer.

    Do you mean creating an instance that controls 4 channels at oner?

    I only know the way that APP_PWM_DEFAULT_CONFIG_2CH(800L, 22, 23); So, please let me know how to do that?

    And i also can't find  DECODER.LOAD=Single.

    Thank you 

  • Hi,

    app_pwm is based on a timer and GPIOTE+PPI, it is limited with two channels per instance. Take a look at PWM driver, it uses hardware PWM peripheral that can drive four channels at once. 

    Here is a draft example how to configure pwm for 4 channels:

    static const nrfx_pwm_t pwm = NRFX_PWM_INSTANCE(0);
    
    static const nrfx_pwm_config_t pwm_config = {
        .output_pins = { 13,14,15,16 },
        .irq_priority = 3,
        .base_clock = NRF_PWM_CLK_1MHz,
        .count_mode = NRF_PWM_MODE_UP,
        .top_value = 200,
        .load_mode = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode = NRF_PWM_STEP_AUTO,
    };
    
    static uint16_t pwm_data[16] = { 0x8000,0,0,0,  0,0x8000,0,0,  0,0,0x8000,0,  0,0,0,0x8000 };
    
    static const nrf_pwm_sequence_t pwm_seq = {
        .values.p_raw = pwm_data,
        .length = NRF_PWM_VALUES_LENGTH(pwm_data),
        .repeats = 0,
        .end_delay = 0,
    };
    
    nrfx_pwm_init(&pwm, &pwm_config, NULL);
    nrfx_pwm_simple_playback(&pwm, &pwm_seq, 1, NRFX_PWM_FLAG_LOOP);
    

Related