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

NRF52 PWM strange behaviour of simple_playback playback_count parameter

Hello,

i am using the PWM peripheral in the waveform mode to generate a complementary signals for a piezo beeper connected between two GPIOs.

I use the sequences to play one note at a time and when i receive the PWM_EVT_STOPPED Event, i play the next note.

The frequency is set by the top value and to get 50% duty is set both channels to counter_top/2.

This works, but the simple playback function behaves kind of strange. If a give it a playback_count of 1 the buzzer only clicks, but if I raise it to 2 and more it plays the notes.

Other questions:

-What is the correct way of inverting a PWM channel? Via Pin initialisation or channel value or both?

-I get clicks in the piezo, when there is a BLE communication, what can cause this?

Here  is the code i use:

//PWM  init
static nrf_pwm_values_wave_form_t  seq_values;

nrf_drv_pwm_config_t const config0 =
{
.output_pins =
{
BOARD_BUZ1 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
BOARD_BUZ2, // channel 1
NRF_DRV_PWM_PIN_NOT_USED, // channel 2
NRF_DRV_PWM_PIN_NOT_USED, // channel 3
},
.irq_priority = APP_IRQ_PRIORITY_LOWEST,
.base_clock = NRF_PWM_CLK_16MHz,
.count_mode = NRF_PWM_MODE_UP,
.top_value = 4000,
.load_mode = NRF_PWM_LOAD_WAVE_FORM,
.step_mode = NRF_PWM_STEP_AUTO
};
APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, buzzer_handler));

//Setting up sequence
seq.values.p_wave_form = &seq_values;
seq.length = NRF_PWM_VALUES_LENGTH(seq_values);
seq.repeats = 0;
seq.end_delay = 0;

//Playing a note
seq_values.channel_0=beeper_note_ptr->note/2;
seq_values.channel_1=seq_values.channel_0;
seq_values.channel_2 =0;
seq_values.counter_top =beeper_note_ptr->note;

seq.repeats = (beeper_note_ptr->duration*beeper_note_ptr->note)/1000;
seq.end_delay = beeper_note_ptr->delay;

nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 2, NRF_DRV_PWM_FLAG_STOP);

Parents
  • Try this to invert:

    seq_values.channel_1=seq_values.channel_0 | 0x8000;

    Try adding a second "note" of silence to allow single count, so play always real note and silence; silence will allow setting of '1'.:

    typedef enum {
    // One-Line 4     PWM                 PWM     PWM   Repeat
    //                Count       Freq    Count   Count  Count
    // ========      ======    =======   =======  =====   ====
    blah-blah
     Ps4A     =       2273, //   440.00   2272.73   2273    220
    blah-blah
    } Notes_t;
    
    // Middle A is 440Hz, so at 1MHz clock that's (2273-1) ticks or 2723uSecs per line, 4MHz clock 9091 ticks but repeat counts will be same
    // At a beat of 120 bpm one quarter note takes 500mSecs, so 220 total counts, say 22 lines at 10 repeats per line
    static nrf_pwm_values_wave_form_t MiddleA2[] = {
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},  // Duty cycle channel 0, 1 and 2 plus top value in uSecs if clock is 1MHz
      {              0,      0, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {              0,      0, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {              0,      0, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {              0,      0, 0, Ps4A},
    };
    

    This code shows a simple tune, taking care of inter-note silences and the last note correct termination. Notice the "0x8000" to get true differential channel PWM.

    The BLE click is due to the software-driven coding you are using; the example just above uses only DMA with no code, no interrupts and therefore no "click".

    You might find my MP3 and nRF52 Piano post useful, requesting a hardware improvement to the nRF52 to allow much smaller RAM required for playing musical scores (and other streaming PWM applications, of course) :-)

Reply
  • Try this to invert:

    seq_values.channel_1=seq_values.channel_0 | 0x8000;

    Try adding a second "note" of silence to allow single count, so play always real note and silence; silence will allow setting of '1'.:

    typedef enum {
    // One-Line 4     PWM                 PWM     PWM   Repeat
    //                Count       Freq    Count   Count  Count
    // ========      ======    =======   =======  =====   ====
    blah-blah
     Ps4A     =       2273, //   440.00   2272.73   2273    220
    blah-blah
    } Notes_t;
    
    // Middle A is 440Hz, so at 1MHz clock that's (2273-1) ticks or 2723uSecs per line, 4MHz clock 9091 ticks but repeat counts will be same
    // At a beat of 120 bpm one quarter note takes 500mSecs, so 220 total counts, say 22 lines at 10 repeats per line
    static nrf_pwm_values_wave_form_t MiddleA2[] = {
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},  // Duty cycle channel 0, 1 and 2 plus top value in uSecs if clock is 1MHz
      {              0,      0, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {              0,      0, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {              0,      0, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {0x8000|(Ps4A/2), Ps4A/2, 0, Ps4A},
      {              0,      0, 0, Ps4A},
    };
    

    This code shows a simple tune, taking care of inter-note silences and the last note correct termination. Notice the "0x8000" to get true differential channel PWM.

    The BLE click is due to the software-driven coding you are using; the example just above uses only DMA with no code, no interrupts and therefore no "click".

    You might find my MP3 and nRF52 Piano post useful, requesting a hardware improvement to the nRF52 to allow much smaller RAM required for playing musical scores (and other streaming PWM applications, of course) :-)

Children
No Data
Related