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

Inverting PWM in nRF52840 pinn

Hello,

I want to output in one pin 400kHz and inverse of 400kHz in the other pin. I have somehow managed to output the the 400kHz but haven't managed to output its inverse.

Here is my code:

#include <stdio.h>
#include <string.h>
#include "nrf_drv_pwm.h"
#include "app_util_platform.h"
#include "app_error.h"
#include "boards.h"
#include "bsp.h"
#include "app_timer.h"
#include "nrf_drv_clock.h"
#include "nrf_delay.h" 
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"


#define m_top     20 
#define m_step    1 

#define  led_external  26 
#define  led_reversed  27

static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);


uint16_t step = m_top / m_step;

static nrf_pwm_values_common_t sequence_values[m_step * 2]; 	

uint16_t value = 0;



static void pwm_common_init(void)
{

    for(int i = 0; i<m_step; i++)
    {
		
      value += step; 
      sequence_values[i] = value;
      sequence_values[m_step + i] = m_top - value; 
    }

    nrfx_pwm_config_t const config0 = 
    {
      .output_pins = 
      {
          led_external,
          led_reversed| NRFX_PWM_PIN_INVERTED,
          NRFX_PWM_PIN_NOT_USED, 
          NRFX_PWM_PIN_NOT_USED 
      },
      .irq_priority = APP_IRQ_PRIORITY_LOWEST, 
      .base_clock   = NRF_PWM_CLK_16MHz, 
      .count_mode   = NRF_PWM_MODE_UP, 
      .top_value    = m_top, 
      .load_mode    = NRF_PWM_LOAD_COMMON, 
      .step_mode    = NRF_PWM_STEP_AUTO

    };
    APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));
}
static void pwm_play(void)
{
  nrf_pwm_sequence_t const seq0 = 
  {
    .values  = sequence_values, 
    .length           = NRF_PWM_VALUES_LENGTH(sequence_values), 
    .repeats          = 0, 
    .end_delay        = 0 
  
  };
  (void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1, NRFX_PWM_FLAG_LOOP);

  }



static void log_init(void)
{
  ret_code_t err_code = NRF_LOG_INIT(NULL);
  APP_ERROR_CHECK(err_code);

  NRF_LOG_DEFAULT_BACKENDS_INIT();

  }





int main(void)
{
log_init();
bsp_board_init(BSP_INIT_LEDS);
pwm_common_init();
pwm_play();

  NRF_LOG_INFO("PWM application started!!");
   
}

I was looking into the previous answers but I wasn't able to still apply their solution into my program. From what I know so far is that "NRFX_PWM_PIN_INVERTED" only works in idle state and that "seq_values->channel_0 = duty_cycle | 0x8000" is a possible answer but I am not sure how to integrate that in my program. 

Asking for help/advice how to integrate 400kHz output in pin 0.26 and inverse 400kHz frequency in pin 0.27 of nRF52840 board thru modifying my code?

Parents Reply Children
  • Hi,

    I made one example that shows how to get 50% with GROUPED mode. Suggest you refer to nrf52840 ps section PWM and nRF52 nRF5 SDK example pwm_driver to learn how to use PWM peripheral on nRF52 devices. 

    #include <stdio.h>
    #include <string.h>
    #include "nrf_drv_pwm.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "boards.h"
    #include "bsp.h"
    #include "app_timer.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h" 
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    
    #define m_top     20 
    #define m_step    1 
    
    #define  led_external  26 
    #define  led_reversed  27|NRFX_PWM_PIN_INVERTED
    
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    
    uint16_t step = m_top / m_step;
    
    static nrf_pwm_values_grouped_t sequence_values[]=    {
            { 0x8000, 0 },
            { 0, 0x8000 }
        };	
    
    
    uint16_t value = 0;
    
    
    static void pwm_common_init(void)
    {
        nrfx_pwm_config_t const config0 = 
        {
          .output_pins = 
          {
              led_external,
              NRFX_PWM_PIN_NOT_USED, 
              led_reversed| NRFX_PWM_PIN_INVERTED,
              NRFX_PWM_PIN_NOT_USED 
          },
          .irq_priority = APP_IRQ_PRIORITY_LOWEST, 
          .base_clock   = NRF_PWM_CLK_16MHz, 
          .count_mode   = NRF_PWM_MODE_UP, 
          .top_value    = m_top, 
          .load_mode    = NRF_PWM_LOAD_GROUPED, 
          .step_mode    = NRF_PWM_STEP_AUTO
    
        };
        APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));
    }
    static void pwm_play(void)
    {
      nrf_pwm_sequence_t const seq0 = 
      {
        .values.p_grouped  = sequence_values, 
        .length           = NRF_PWM_VALUES_LENGTH(sequence_values), 
        .repeats          = 0, 
        .end_delay        = 0 
      
      };
      (void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1, NRFX_PWM_FLAG_LOOP);
    
      }
    
    
    
    static void log_init(void)
    {
      ret_code_t err_code = NRF_LOG_INIT(NULL);
      APP_ERROR_CHECK(err_code);
    
      NRF_LOG_DEFAULT_BACKENDS_INIT();
    
      }
    
    
    
    
    
    int main(void)
    {
    log_init();
    bsp_board_init(BSP_INIT_LEDS);
    pwm_common_init();
    pwm_play();
    
      NRF_LOG_INFO("PWM application started!!");
       
    }

  • 50% with GROUPED mode

    If I needed 80% duty cycle, is that still possible in the program? or do I have to change something like the GROUPED mode into another example Individual?

  • The decoder load mode decides how a sequence is read from ram and spread to the compare register, so it is not related to duty cycle. The duty cycle is decided by compare value in sequence and top value. 

    You want to run 400KHZ 80% duty PWM on Pin26, and reverse output on Pin27, one solution is:

    NRF_PWM_CLK_4MHz //4M/10=400KHZ
    sequence_values[]={2, 2|0x8000,0,10}; // (10-2)/10=80%
    NRF_PWM_LOAD_WAVE_FORM//(See nrf52840 ps section 6.17.1)
    NRF_PWM_MODE_UP //(See nrf52840 ps section 6.17.1)

    Here are the codes with the above settings:

    #include <stdio.h>
    #include <string.h>
    #include "nrf_drv_pwm.h"
    #include "app_util_platform.h"
    #include "app_error.h"
    #include "boards.h"
    #include "bsp.h"
    #include "app_timer.h"
    #include "nrf_drv_clock.h"
    #include "nrf_delay.h" 
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #define  led_external  26 
    #define  led_reversed  27
    
    static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
    
    
    
    static nrf_pwm_values_wave_form_t sequence_values[]={2, 2|0x8000,0,10};	
    
    
    uint16_t value = 0;
    
    
    static void pwm_waveform_init(void)
    {
        nrfx_pwm_config_t const config0 = 
        {
          .output_pins = 
          {
              led_external,
              led_reversed,
              NRFX_PWM_PIN_NOT_USED,   
              NRFX_PWM_PIN_NOT_USED 
          },
          .irq_priority = APP_IRQ_PRIORITY_LOWEST, 
          .base_clock   = NRF_PWM_CLK_4MHz, 
          .count_mode   = NRF_PWM_MODE_UP,  
          .load_mode    = NRF_PWM_LOAD_WAVE_FORM, 
          .step_mode    = NRF_PWM_STEP_AUTO
    
        };
        APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));
    }
    static void pwm_play(void)
    {
      nrf_pwm_sequence_t const seq0 = 
      {
        .values.p_wave_form  = sequence_values, 
        .length           = NRF_PWM_VALUES_LENGTH(sequence_values), 
        .repeats          = 1, 
        .end_delay        = 0 
      
      };
      (void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1, NRFX_PWM_FLAG_LOOP);
    
      }
    
    
    
    static void log_init(void)
    {
      ret_code_t err_code = NRF_LOG_INIT(NULL);
      APP_ERROR_CHECK(err_code);
    
      NRF_LOG_DEFAULT_BACKENDS_INIT();
    
      }
    
    
    
    
    
    int main(void)
    {
    log_init();
    bsp_board_init(BSP_INIT_LEDS);
    pwm_waveform_init();
    pwm_play();
    NRF_LOG_INFO("PWM application started!!");
       
    }

Related