Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

PWM library simpler way for on/off (enable/disable) than the example with SDK?

Is there a way to set duty cycle before app_pwm_enable(&PWM1) call ?

Or some other simple way to switch on and off a passive buzzer signal without every time at off/on cycle to go with complex sequence for setting duty value as per pwm_library example?

Let say some app like Morse Code where the frequency will be resonance of the buzzer and duty cycle will be constant 50 (or less).

Thanks

Parents
  • Hi 

    You mean you only want to turn on/off a simple square wave where the frequency and duty cycle will always be the same?

    If this is the case it might be easier just to use a timer to generate events, and connect them to  a GPIO through the GPIOTE and PPI peripherals. 

    Then you can set the frequency simply by changing the compare value in the timer. 

    Best regards
    Torbjørn

  • Ok, I tried the gpiote example and browse documentation. But still cant find what is(are) the way once I start the square wave, to stop it , then to restart it (with minimum operations)?

    While in stopped/idle mode – is there any of those components involved:  timer, gpiote, ppi  that would consumes excessive power (in a scale for a battery operated devices) that I have to be worry about?

    Thanks

  • Hi 

    A running timer will increase the sleep current considerably, yes, so I would recommend stopping it whenever the square wave is not needed. 

    The best way to do this is to activate the SHUTDOWN task in the timer, which disables it completely. 

    Having a PPI channel or a GPIOTE OUT channel enabled should not affect the sleep current significantly, but I will have to double check this to be sure and get back to you. 

    Best regards
    Torbjørn

  • Ok, but timers SHUTDOWN task is marked in documentation as “Deprecated”?

    Your idea for using timer to generate the basic frequency (I need 2730 Hz) is very good, I only struggle to find documentation or example how best to switch on /off this square wave with GPIOTE as I will use it for audio markers 1 to 4 beeps: let say 1 beep immediately after a button is pressed, 2 for long press, 3 , 4. Also beeps(and pauses between) could   be short or long etc.

    I anyway will use 1MHz(or less) timer source, so will spend less power at those frequencies, but looking to find optimal solution to switch off/on the 2730 burst in between beeps of a single audio prompt, then move timer and all other involved components (GPIOTE, PPI or whatever will use) in idle position waiting to start new audio prompt with minimum reinitializations.

    Thank you and best regards

  • Hi 

    It is true that the SHUTDOWN task is marked as deprecated, but for devices affected by Errata 78 it is necessary to use this task to achieve low current consumption in sleep mode. 

    In future devices where this issue is fixed you would have to replace the SHUTDOWN task with the STOP task. 

    If you want to stop and start the timer at a slower rate you can use the app_timer to schedule this. 

    I made a small example based on ble_app_uart to show how you can configure the TIMER, PPI and GPIOTE peripherals, and use the app_timer to start and stop the timer repeatedly:

    1715.ble_app_uart_timer_freq.zip

    Best regards
    Torbjørn

Reply
  • Hi 

    It is true that the SHUTDOWN task is marked as deprecated, but for devices affected by Errata 78 it is necessary to use this task to achieve low current consumption in sleep mode. 

    In future devices where this issue is fixed you would have to replace the SHUTDOWN task with the STOP task. 

    If you want to stop and start the timer at a slower rate you can use the app_timer to schedule this. 

    I made a small example based on ble_app_uart to show how you can configure the TIMER, PPI and GPIOTE peripherals, and use the app_timer to start and stop the timer repeatedly:

    1715.ble_app_uart_timer_freq.zip

    Best regards
    Torbjørn

Children
  • Hi Torbjørn,

    Really appreciate the time you spent to prepare so long example. I definitely get far more useful information from your code than from the infocenter. I just spend only about an hour and not sure I’ve got right all the operations, not tried yet on the DK. The only part of the code I have certain concerns is

        SOUND_TIMER->TASKS_SHUTDOWN = 1;

        NRF_GPIOTE->TASKS_CLR[SOUND_GPIOTE_CH] = 1;

    I read in the specs that timer tasks have delays: for CLEAR, START and STOP it says is “one clock cycle of the PCLK16M”, but doesn’t says nothing about TASKS_SHUTDOWN and PCLK1M. So I’l have to test somehow not to happened situation when NRF_GPIOTE->TASKS_CLR happened before actual SOUND_TIMER shutdown, because then there is a chance SOUND_TIMER to be shut down while the output is in high level, and then buzzer will not buzz, but will spend 100mA …  I currently work on some other part of the project, but as soon as I finish this one will return back to buzzer story.

    As you said some nRF52840 chips have some bug, how can get from code chip version? Because by the time I finish this project maybe those old versions will be gone and maybe worth to check in code if the chip is affected by this bug and if so to use TASKS_SHUTDOWN else TASKS_STOP?

    Thank you, very much and best regards

    P.S. If I have to start from scratch such code that you wrote - how could find all those 'defines' for registers, values, positions etc. that you used like GPIOTE_CONFIG_MODE_Task, GPIOTE_CONFIG_OUTINIT_Low ... 

    Is there any documentation, manual, tutorial, etc? Let say register names are same what is in the spec sheet for the particular device, but all the rest - no clue. I can trace the source from your code, but if I start from scratch I would be as a new world explorer :(

  • Hi

    Regarding the delay for stopping the timer and clearing the output pin, both these delays are consistent, so if shutting down the timer was slower than clearing the pin you would see it all the time. 

    I haven't connected my example to a buzzer, but I check the signal on a scope to verify that it turns off as expected. 

    That said there is a microscopic chance that you will get an interrupt in between the call to SOUND_TIMER->TASKS_SHUTDOWN = 1 and NRF_GPIOTE->TASKS_CLR[SOUND_GPIOTE_CH] = 1, and if this happens the pin could be held high for the duration of the interrupt. 

    One way to solve this is to wrap these two calls in a critical section, or you could try to change the sound_start and sound_stop functions like this:

    static void sound_start(void)
    {
        NRF_PPI->FORK[SOUND_PPI_CH_B].TEP = 0;
        SOUND_TIMER->TASKS_CLEAR = 1;
        SOUND_TIMER->TASKS_START = 1;
    }
    
    static void sound_stop(void)
    {
        NRF_PPI->FORK[SOUND_PPI_CH_B].TEP = (uint32_t)&SOUND_TIMER->TASKS_SHUTDOWN;
    }

    The modified code I added essentially makes the timer shut off itself when it reaches the value stored in the CC[1] register, which ensures there is no room for code interrupts etc to affect it. 

    samsam said:
    As you said some nRF52840 chips have some bug, how can get from code chip version?

    The nRF52840 has been out for many years already, so it is extremely unlikely that this bug will be fixed in a future update. 

    Making a new revision of a chip is very expensive, and requires a lot of engineering time, so we usually don't do this unless the bug is very critical or there are no software workarounds available. 

    Still, if you ever need to read the chip revision it is available in the FICR->INFO.VARIANT register. 

    samsam said:
    P.S. If I have to start from scratch such code that you wrote - how could find all those 'defines' for registers, values, positions etc. that you used

    All the register values can be found in the nrf52840_bitfields.h file. 

    I agree all this is a bit overwhelming in the start, but once you get used to the syntax (PERIPHERAL_REGISTER_FIELD_VALUE) and you have auto complete working in Segger Embedded Studio it gets easier to work with ;)

    As for tutorials we many available here, I would definitely recommend reading some of the getting started guides.

    Best regards
    Torbjørn

  • Hi Torbjørn,

    I just check the code you've sent before on nRF42 DK as well measure the frequency - works Ok so far.

    Could you explain  this line from you code, please:

    SOUND_TIMER->CC[2] = ((16000000 / (1 << SOUND_TIMER_PRESCALER)) + (frequency / 2)) / frequency;

    which looks initially scary ;), but simplified is

    = (16000000 / (1 << SOUND_TIMER_PRESCALER))/frequency +0.5;

    Why is this 0.5 - only to to round on the upper integer or there is something else that I'm missing?

    Thank you very much and best regards!

  • Hi

    It's just to round to the closest integer value, yes (rather than always rounding down) to ensure the frequency is as close as possible to the intended value. 

    Similar to the code snippet below from this stackoverflow case:

    unsigned int round_closest(unsigned int dividend, unsigned int divisor)
    {
        return (dividend + (divisor / 2)) / divisor;
    }

    Best regards
    Torbjørn

  • Thanks, will take a closer look at stackoverflow - good to know all issues when computer math doesn't follow standard math :)

    Regarding tutorials that you refer to in the previous post - I think I passed most valuable tutorials published there couple months ago when started actively evaluating nRF52, but didn't remember any place tutoring how to work direct with nRF registers. Let say in my particular case is more interesting what is the naming convention for all those defines that are made especially to facilitate work with registers, and in which files/locations are they. Browsed yesterday again your link to tutorials and didn't find anything new that might be related? If you know for sure that such information for working with registers is available somewhere, could  you point it or at least give me a hint what to search for, because there are tons of tutorials there and is quite possible I could miss it?

    Thank you and best regards

Related