NRF52840 nrf nrfx PWM glitching complex waveform

I need to create some complex waveforms and my strategy is to use nrfx_pwm_complex_playback to play one waveform then the other as a seamless loop; and I'll manipulate the sequence that's not currently being played and it should then switch in at the end of the current sequence.

I've set up the most simple case with two sequences. It's looping but the waveform is not good - single pulses popping up. This isn't finished code but should be complete.

What am I missing? Thanks!

static nrf_pwm_values_common_t sequence_data[ 2 ][ 100 ];

static nrf_pwm_sequence_t sequences[ 2 ];


static nrfx_pwm_config_t const config_motor =
{
.output_pins =
{
IO_PIN_MOTOR_PWM, // channel 0
NRFX_PWM_PIN_NOT_USED, // channel 1
NRFX_PWM_PIN_NOT_USED, // channel 2
NRFX_PWM_PIN_NOT_USED // channel 3
},
.irq_priority = 5,
.base_clock = NRF_PWM_CLK_8MHz, // Originally 8MHz
//.base_clock = NRF_PWM_CLK_1MHz, // Originally 8MHz
//.base_clock = NRF_PWM_CLK_125kHz,
.count_mode = NRF_PWM_MODE_UP,
//.top_value = 2500,
.top_value = 255,
.load_mode = NRF_PWM_LOAD_COMMON,
.step_mode = NRF_PWM_STEP_AUTO
};

  nrfx_pwm_init(&pwm_motor, &config_motor, NULL, NULL);

void io_spwm_motor_complex_flat( uint8_t seqIndex , uint32_t duty , uint16_t periods ) {
duty = 255 - duty;

sequence_data[ seqIndex ][ 0 ] = (duty <= 255 ) ? duty : 255 ;

sequences[ seqIndex ] = ( nrf_pwm_sequence_t )
{
.values.p_common = sequence_data[ seqIndex ],
.length = 1,
.repeats = periods,
.end_delay = 0
};
nrfx_pwm_sequence_update( &pwm_motor , seqIndex , &sequences[ seqIndex ] );
}

void io_spwm_complex_restart(uint32_t duty )
{
io_spwm_motor_complex_flat( 0 , 64 , 4 );
io_spwm_motor_complex_flat( 1 , 250 , 4 );

(void)nrfx_pwm_complex_playback(&pwm_motor, &sequences[ 0 ] , &sequences[ 1 ] , 2 , NRFX_PWM_FLAG_LOOP );

//(void)nrfx_pwm_simple_playback(&pwm_motor, &sequences[ 1 ] , 1, NRFX_PWM_FLAG_LOOP);

}

io_spwm_complex_restart( 1 );

Parents
  • Hi Nick

    I don't quite understand which pulses you are talking about by looking at the figure. 

    If I understand your code correctly the PWM switches between 64/255, which are the short pulses, and 250/255, which is the other state where it is mostly high but will drop down shortly for each PWM period. 

    To me the diagram looks OK, but maybe it is something I am missing?

    If you can share your code as a C file I can also try to reproduce the issue here. 

    Best regards
    Torbjørn

  • From the SDK

    "The repeats and end_delay values (which are written to the SEQ[n].REFRESH and SEQ[n].ENDDELAY registers in the peripheral, respectively) are ignored at the end of a complex sequence playback, indicated by the LOOPSDONE event. See the Product Specification for more information."

    So how do I continuously loop two sequences, where the last uses .repeats? I have to create a data stream of that length? Very inefficient to fill an array with values.

  • Hi Nick

    Now I understand the issue, I didn't spot this in the diagram earlier...

    Yes, this is a limitation in the hardware unfortunately. 

    If you give me a bit more information about what the PWM pulse should be used for maybe we can come up with a different approach to implementing this. 

    For instance, how big of a repeat counter are you planning to use in the actual application, and what is the length of the buffers?

    Could it be an alternative to step through the buffer manually using the NextStep decoder mode?
    In this mode you will be in more direct control of when the PWM moves to the next value in the DMA buffer, which means you can indirectly set the number of repeats based on how often you trigger the NEXTSTEP task. 

    Best regards
    Torbjørn

Reply
  • Hi Nick

    Now I understand the issue, I didn't spot this in the diagram earlier...

    Yes, this is a limitation in the hardware unfortunately. 

    If you give me a bit more information about what the PWM pulse should be used for maybe we can come up with a different approach to implementing this. 

    For instance, how big of a repeat counter are you planning to use in the actual application, and what is the length of the buffers?

    Could it be an alternative to step through the buffer manually using the NextStep decoder mode?
    In this mode you will be in more direct control of when the PWM moves to the next value in the DMA buffer, which means you can indirectly set the number of repeats based on how often you trigger the NEXTSTEP task. 

    Best regards
    Torbjørn

Children
No Data
Related