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

Disable and enable the PWM on a Thingy:91

Hello,

I'm having a bit of difficulty disabling the PWM peripheral when it is no longer required. From the manual it states that "To completely stop the PWM generation and force the associated pins to a defined state, a STOP task can be triggered at any time.", so I have triggered a TASKS_STOP call followed by disabling the peripheral with ENABLE but it doesn't seem to stop the PWM driven pins.

void pwm_control(CTRL *pCtrl, bool enable)
{
  #if CONFIG_PWM
  {
    if(enable && !pCtrl->System_PWM.bPWMEnable)
    {
      printk("Enabling PWM\n");

      NRF_PWM1_NS->ENABLE = 1;
      NRF_PWM1_NS->TASKS_SEQSTART[0] = 1;

      pCtrl->System_PWM.bPWMEnable = true;
    }
    else if (!enable && pCtrl->System_PWM.bPWMEnable)
    {
      printk("Disabling PWM\n");

      NRF_PWM1_NS->TASKS_STOP = 1;
      NRF_PWM1_NS->ENABLE = 0;

      pCtrl->System_PWM.bPWMEnable = false;
    }
    else
    {
      printk("Error, PWM control undetermined\n");
    }
  }
  #endif
}

What I see is that if I place the above function after a call to pwm_pin_set_usec(), the PWM driven pin is still driven, e.g. the Thingy:91 RGB LED is still illuminated, and any future calls to pwm_pin_set_usec() run as normal with no issues. What is the correct method to disable the PWM perpiheral on the nRF9160 during runtime?

Parents
  • Hi

    Here is the prj.conf file for my application. There are a lot of custom config options in there.

    # Use the development test RNG (not for production)
    CONFIG_TEST_RANDOM_GENERATOR=y
    
    # Networking, enable networking APIs
    CONFIG_NETWORKING=y
    CONFIG_NET_SOCKETS_OFFLOAD=y
    CONFIG_NET_SOCKETS=y
    
    # Allow Socket APIs to use POSIX names like socket(), send(), etc
    # Careful with close(), close() only works on sockets when enabled
    CONFIG_NET_SOCKETS_POSIX_NAMES=y
    
    # BSD library
    CONFIG_BSD_LIBRARY=y
    
    # Main thread, reuse init stack
    CONFIG_MAIN_THREAD_PRIORITY=4
    CONFIG_MAIN_STACK_SIZE=4096
    
    # Available memory for k_malloc
    CONFIG_HEAP_MEM_POOL_SIZE=2048
    
    # Build with newlib c library
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    
    # Enable non-secure firmware as Normal mode
    CONFIG_TRUSTED_EXECUTION_NONSECURE=y
    
    # Enable Flash Memory Management
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    
    # Enable NVS File System
    CONFIG_NVS=y
    CONFIG_NVS_LOG_LEVEL_DBG=y
    CONFIG_MPU_ALLOW_FLASH_WRITE=y
    
    # Include GPIO drivers
    CONFIG_GPIO=y
    
    # Enable options for serial drivers
    CONFIG_SERIAL=y
    
    # Enable UART Interrupt support
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_UART_1_NRF_UARTE=y
    
    # Include support for watchdogs
    CONFIG_WATCHDOG=y
    
    # Define WDT timeout counter
    CONFIG_WDT_TIMEOUT_MSEC=5000
    
    # Allow threads to use the Floating Point Unit Register
    CONFIG_FLOAT=y
    
    # Enable the sys_reboot() API
    CONFIG_REBOOT=y
    
    # Enables the __ASSERT() macro in the kernel code
    CONFIG_ASSERT=y
    
    # Enable GPS only test mode
    CONFIG_GPS_TEST=n
    
    # Configure Callback1 for NVS readout
    CONFIG_BUTTON_NVS_PRINT_OUT=n
    
    # Define modem power saving timeouts
    CONFIG_MODEM_SLEEP_TIME=180
    CONFIG_MODEM_ATTACH_TIMEOUT=20
    CONFIG_MODEM_SLEEP_MAX_DELAY=40
    
    # Define GPS power saving timeouts
    CONFIG_GPS_ACTIVE_TIME=20
    CONFIG_GPS_SLEEP_TIME=60
    
    # Define UDP packet characteristics
    CONFIG_MAX_NVS_PER_UDP_MESSAGE=50
    CONFIG_MAX_BYTES_PER_UDP_MESSAGE=2145
    
    # Define maximum number of Flash Pages and Entries
    CONFIG_FLASH_SECTORS=102
    CONFIG_MAX_NVS_ENTRIES=8550
    
    # Enable Flash Preservation UDP Transport
    CONFIG_APP_HOTSWAP=y
    
    # Enable and configure battery level polling
    CONFIG_VBATT_MEASURE=y
    CONFIG_VBATT_TIMER=60
    CONFIG_CRITICAL_BATT_LVL=3200
    
    # Configure AT Timeout
    CONFIG_AT_TIMEOUT=60
    
    # Configure GPS Locking time
    CONFIG_GPS_FIXES=120
    
    #################
    # Disable the following when building for the nRF9160 DK
    # Set Board Configuration for the PCA20035NS and V0_3_0NS
    # Comment out when building for any other device
    CONFIG_BOARD_NRF9160_PCA20035NS=y
    CONFIG_BOARD_NRF9160_PCA20035_V0_3_0NS=y
    
    # Configure Callback1 for motion detection
    CONFIG_SPI_INT1=y
    
    # Configure SPI XYZ tests
    CONFIG_SPI_XYZ=n
    
    # Enable config options for PWM drivers, enable PWM on port 1 and set PWM period
    CONFIG_PWM=y
    CONFIG_PWM_1=y
    CONFIG_PWM_PERIOD=370
    CONFIG_BUZZER_VOLUME=100
    
    # Enable SPI hardware bus support and enable SPI on port 3
    CONFIG_SPI=y
    CONFIG_SPI_3=y
    
    # Enable support for nrfx SPI drivers for nRF MCU series.
    CONFIG_SPI_NRFX=y
    
    # Enable nRF SPI Master with EasyDMA on port 3.
    CONFIG_SPI_3_NRF_SPIM=y
    #######################
    #######################
    # Set the following to 'n' to suppress the serial output and disable UART0
    # Enable stdout for printfs.
    CONFIG_STDOUT_CONSOLE=y
    
    # Global switch for the logger, when turned off log calls will not be compiled in.
    CONFIG_LOG=y
    CONFIG_LOG_DEFAULT_LEVEL=4
    
    # Outputs a banner to the console device during boot up.
    CONFIG_BOOT_BANNER=y
    
    # Outputs debugging printk calls to the console instead of suppressing them.
    CONFIG_PRINTK=y
    ######################

  • Okay, thank you. 

    The correct way to disable PWM is exactly what you are doing. Have you confirmed that the PWM driven pin is not just constant high or low? And you're sure the code enters the else-if?

  • Is that likely to be the case with the PWM driven LEDs on a PCA20035 device? I would have thought that the PWM generation halt would have returned the pin to an idle state and the MOSFET would stop allowing the LED to light as the PWM voltage has stopped.

    However I still see the code able to use the LED pins when called using pwm_pin_set_usec() after calling this block of code, it definitely enters the else-if as I see the 'Disabling PWM' printk() fire.

    To test the code, I have my full application running a specific LED colour (RGB set to different PWM values to represent different states and activities) and then calling this function immediately after a block of code that uses the LEDs. What I see is the function fires correctly and then hits the else statement every time it next gets fired, which is correct behaviour as I am not enabling the PWM ever so the 'bPWMEnable' flag is now permanently false, I just want to test that it will disable it.

    What I see from the device is that the Thingy will still run it's PWM functions as normal even though the PWM should be disabled.

    Can pwm_pin_set_usec() still drive the pins as normal High/Low gpios if PWM is offline?

    EDIT:

    I stuck a call to the buzzer into the same place after I call pwm_control() and the buzzer isn't sounding so something has happened but the LEDs are still working. Is the question above actually the case with pwm_pin_set_usec().

    Looking at the LEDs a bit more deeply, what I see is that if the colour I am choosing uses the full PWM on a specific pin, it will be lit but if it is a value of less than the full PWM, it will be unlit.

    E.G. Purple is:

          /* PURPLE */
          {
            .iRed   = PWM_PERIOD,
            .iGreen = 0,
            .iBlue  = PWM_PERIOD/5
          },

    What I see when the pwm_control() function is called is just Red and no blue.

  • Hi, I apologize for the slow response. 

     

    MJD093 said:
    Can pwm_pin_set_usec() still drive the pins as normal High/Low gpios if PWM is offline?

     No. I just tested this to confirm, and this function cannot drive the pins when the PWM is disabled.

    I'm waiting for a response internally as to what your issue could be.

    Best regards,

    Heidi

  • Hi Heldi,

    Ok so that's strange that the function still can operate. I am having bizarre results in handling the PWM peripheral.

    I have implimented the disable and re-enable code into my application and find that the LED control functions do not engage the LEDs after the PWM is restarted, all I see is the debug lines in the control functions printing to the terminal showing that pwm_pin_set_usec() is not returning an err value and thus should be setting the LED to a specific colour, i.e. blue.

    These control functions are embedded into an operation function that compress tasks like GPS locking or NB-IoT connections into a single function call. I have to make a direct call to my PWM functions (either for the LEDs or the Buzzer) that contain the pwm_pin_set_usec() commands (or just call that command once in the main.c file) in order for the LEDs to be driven normally by the operational functions.

    What I mean is shown below:

    void operational_function(void)
    {
        /*some code*/
        led_control(); /*does not operate LEDs after the PWM is disabled and restarted*/
    }
    

Reply
  • Hi Heldi,

    Ok so that's strange that the function still can operate. I am having bizarre results in handling the PWM peripheral.

    I have implimented the disable and re-enable code into my application and find that the LED control functions do not engage the LEDs after the PWM is restarted, all I see is the debug lines in the control functions printing to the terminal showing that pwm_pin_set_usec() is not returning an err value and thus should be setting the LED to a specific colour, i.e. blue.

    These control functions are embedded into an operation function that compress tasks like GPS locking or NB-IoT connections into a single function call. I have to make a direct call to my PWM functions (either for the LEDs or the Buzzer) that contain the pwm_pin_set_usec() commands (or just call that command once in the main.c file) in order for the LEDs to be driven normally by the operational functions.

    What I mean is shown below:

    void operational_function(void)
    {
        /*some code*/
        led_control(); /*does not operate LEDs after the PWM is disabled and restarted*/
    }
    

Children
No Data
Related