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

    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

  • Hi 

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

    It's integer math basically. When I started in Nordic we were still using 8-bit microcontrollers with only 16kB of code flash, and you didn't use float unless you really had no other choice. 

    In the nRF52 you could easily just convert to float and do the calculations in a more intuitive way, but staying with integer operations exclusively is still a bit more efficient ;)

    samsam said:
    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?

    I don't think there are any tutorials or guides for this as such. The intention behind the SDK is to provide drivers and abstractions so you don't have to access hardware directly, but I often find the hardware easier to deal with than some of the drivers ;)

    What I can give you is a link to a repository full of hardware level examples, showing how you can use most of the peripherals in the nRF52 by accessing registers only. These examples should give you a good indication to what kind of registers are available, and how to access them:

    https://github.com/andenore/NordicSnippets

    Just open the "examples" folder for all the different examples. 

    Best regards
    Torbjørn

Reply
  • Hi 

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

    It's integer math basically. When I started in Nordic we were still using 8-bit microcontrollers with only 16kB of code flash, and you didn't use float unless you really had no other choice. 

    In the nRF52 you could easily just convert to float and do the calculations in a more intuitive way, but staying with integer operations exclusively is still a bit more efficient ;)

    samsam said:
    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?

    I don't think there are any tutorials or guides for this as such. The intention behind the SDK is to provide drivers and abstractions so you don't have to access hardware directly, but I often find the hardware easier to deal with than some of the drivers ;)

    What I can give you is a link to a repository full of hardware level examples, showing how you can use most of the peripherals in the nRF52 by accessing registers only. These examples should give you a good indication to what kind of registers are available, and how to access them:

    https://github.com/andenore/NordicSnippets

    Just open the "examples" folder for all the different examples. 

    Best regards
    Torbjørn

Children
No Data
Related