This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

The Buzz's frequency for CC2650 SensorTag is wrong?

Other Parts Discussed in Thread: CC2640, CC2650

Hi,

         I found there is a bug related to buzz frequency in TI BLE SDK, the original code looks like below:

static void initBuzzTimer(void)
{
Clock_Params clockParams;

// Setup parameters.
Clock_Params_init(&clockParams);

// Setup argument.
clockParams.arg = 0;

// Period
clockParams.period = BUZZER_PERIOD;

// Do not start until called.
clockParams.startFlag = false;

// Initialize clock instance.
Clock_construct(&buzzClockStruct, timerIsr, BUZZER_PERIOD, &clockParams);
buzzClockHandle = Clock_handle(&buzzClockStruct);
}

But I think the correct version is:

clockParams.period = BUZZER_PERIOD; ==> clockParams.period = BUZZER_PERIOD * (1000 / Clock_tickPeriod);

           And

 Clock_construct(&buzzClockStruct, timerIsr, BUZZER_PERIOD, &clockParams); ==> Clock_construct(&buzzClockStruct, timerIsr, BUZZER_PERIOD * (1000 / Clock_tickPeriod), &clockParams);

         After above modifications, I found the output buzz's frequency is 250HZ if I set BUZZER_PERIOD to BUZZER_PERIOD_500HZ, why the actual frequency is half of desired one?

         Thanks for any suggestion or comments.

  • Hello Ken,

    Thank you for the report. I'll have our SensorTag team review.

    Best wishes
  • Thanks for reporting. For the next BLE release (2.2) the whole buzz timer operation will be replaced by PWM. The current implementation is very inaccurate and resource-consuming (and only there to indicate if the buzzer works or not).

  • Hi Jomar,

               Thanks! We need fix this for our important customer... when next BLE release 2.2 ready? Could I use BLE release 2.1 + PWM to fix this as quick as possible? Sorry for these questions, but this really bring much trouble for us!

    Ken

  • Yes, the new buzzer driver is part of the latest TI-RTOS. Please find the necessary files attached.8463.buzzer.h

    6825.buzzer.c
    /*
     * Copyright (c) 2015, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /** ============================================================================
     *  @file       buzzer.c
     *
     *  @brief      PWM-based buzzer interface.
     *  ============================================================================
     */
    
    /* -----------------------------------------------------------------------------
    *  Includes
    * ------------------------------------------------------------------------------
    */
    
    // TI RTOS drivers
    #include <ti/sysbios/family/arm/cc26xx/Power.h>
    #include <ti/sysbios/family/arm/cc26xx/PowerCC2650.h>
    
    // Temporary PWM solution directly on DriverLib
    // (until a Timer RTOS driver is in place)
    #include <ti/drivers/PIN/PINCC26XX.h>
    #include <driverLib/timer.h>
    
    #include "buzzer.h"
    
    /* -----------------------------------------------------------------------------
    *  Local variables
    * ------------------------------------------------------------------------------
    */
    static PIN_Handle hPin = NULL;
    
    /* -----------------------------------------------------------------------------
    *  Public Functions
    * ------------------------------------------------------------------------------
    */
    
    /*******************************************************************************
     * @fn          buzzerOpen
     *
     * @brief       Initialize the Buzzer
     *
     * @descr       Initializes pin and PWM
     *
     * @return      -
     */
    void buzzerOpen(PIN_Handle hGpioPin)
    {
        hPin = hGpioPin;
    
        // Turn on PERIPH power domain and clock for GPT0 and GPIO
        Power_setDependency(PERIPH_GPT0);
        Power_setConstraint(Power_SB_DISALLOW);
    
        // Assign GPT0
        TimerConfigure(GPT0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM);
    
        // Configure pin for PWM output
        PINCC26XX_setMux(hPin, Board_BUZZER, IOC_PORT_MCU_PORT_EVENT0);
    }
    
    
    /*******************************************************************************
     * @fn          buzzerSetFrequency
     *
     * @brief       Set the frequency (3Hz - 8 KHz)
     *
     * @return      return true if the requency is within range
     */
    bool buzzerSetFrequency(uint16_t freq)
    {
        uint32_t ticks;
        uint32_t loadLow;
        uint32_t loadHigh;
        uint32_t matchLow;
        uint32_t matchHigh;
    
        if (freq < BUZZER_FREQ_MIN && freq > BUZZER_FREQ_MAX)
        {
            return false;
        }
    
        // Stop timer during reconfiguration
        TimerDisable(GPT0_BASE, TIMER_A);
    
        // Calculate timer load and match values
        ticks = 48000000 / freq;
        loadLow = ticks & 0x0000FFFF;
        loadHigh = (ticks & 0x00FF0000) >> 16;
        matchLow = (ticks / 2) & 0x0000FFFF;
        matchHigh = ((ticks / 2) & 0x00FF0000) >> 16;
    
        // Set timer load
        TimerLoadSet(GPT0_BASE, TIMER_A, loadLow);
        TimerPrescaleSet(GPT0_BASE, TIMER_A, loadHigh);
    
        // Set timer match
        TimerMatchSet(GPT0_BASE, TIMER_BOTH, matchLow);
        TimerPrescaleMatchSet(GPT0_BASE, TIMER_A, matchHigh);
    
        // Start timer
        TimerEnable(GPT0_BASE, TIMER_A);
    
        return true;
    }
    
    /*******************************************************************************
     * @fn          buzzerClose
     *
     * @brief       Closes the buzzer interface
     *
     * @return      -
     */
    void buzzerClose(void)
    {
        // Configure pin as GPIO
        PINCC26XX_setMux(hPin, Board_BUZZER, IOC_PORT_GPIO);
    
        // Turn off PERIPH power domain and clock for GPT0
        Power_releaseDependency(PERIPH_GPT0);
        Power_releaseConstraint(Power_SB_DISALLOW);
    }
    

  • Hi Jomar,

              Although without PowerCC26xx.h, but I make your patch work in BLE 2.1 stack!!! It really work very accurate like attached picture which using 500HZ.

              Thank you so much!!!

              However, your patch did not provide buzzerStop(), so I add a new function like below:

              void buzzerStop(void) {

        if (hPin == NULL) {
            return;
        }
        TimerDisable(GPT0_BASE, TIMER_A);
    }

              In SensorTagIO_init(), I will call buzzerOpen(), then I will use buzzerSetFrequency() and buzzerStop() to start/stop buzz.

              My final question: when to call buzzerClose()?

  • I'm glad it helped. I noticed a bug here. The intention was that buzzerSetFrequency(0) should stop the timer but that doesn't work. What I plan to do to fix it is to move the line

    // Stop timer during reconfiguration
    TimerDisable(GPT0_BASE, TIMER_A);

    to the very start of the function.

    NB! You must always call buzzer stop when finished otherwise the MCU will not be allowed to enter standby!

    I would call the sequence buzzerOpen(), buzzerSetFrequency, buzzerClose() together whenever intending to use the buzzzer.
  • Thanks Jomar!
  • Hi Jomar,

    I've found your buzzer files very helpful.  

    In case anyone is interested, I extended the buzzerSetFrequency function to take a duty cycle value as well:

    // Calculate timer load and match values
    ticks = 48000000 / freq;
    loadLow = ticks & 0x0000FFFF;
    loadHigh = (ticks & 0x00FF0000) >> 16;
    matchLow = (ticks * dutycycle / 100) & 0x0000FFFF;
    matchHigh = ((ticks * dutycycle / 100) & 0x00FF0000) >> 16;

    ------------

    I have a question for you, however, regarding the number of concurrent PWM instances that can run.  I haven't seen this answered in the forums but may have missed something.  Your code uses GPT0_BASE and TIMER_A in most of the timer functions, except TimerMatchSet which uses TIMER_BOTH in place of TIMER_A.  Is that a typo - should that be TIMER_A as well?  If this does need to be TIMER_BOTH, please explain why?

    It seems reasonable to expect that GPT1_BASE through GPT3_BASE could all be used in place of GTP0_BASE here, leading me to think we could set up 4 concurrent PWM instances on different IOs.  Is that correct?  If TIMER_A and TIME_B can be used independently then that would go to 8.  Is that a correct interpretation or would there be some issue with using all of those resources (or even more than one) at the same time?

    Many thanks in advance for your help clarifying this point.

    --Allen

  • Hi Allen,

    Thanks for the update!

    You are right, the CC2640 supports8 PWM outputs. More details can be found in the Technical Reference Manual.

    Cheers,
    Fredrik
  • Hello,
    I cannot find the above buzzer implementation in 2.1.1. I assume I've to try to compile the firmware for the Sensor Tag.
    The buzzer output is very low now. The buzzer has its resonant frequency at 2730Hz Or 3000Hz Or 4000Hz.
    Has anyone tried these frequencies? Is it worthed to give it a try?
    Has anyone a prebuilt hex image for the Sensor Tag 2 with a decent buzzer output?

    Thanks,
    Cristiano
  • Hello,

      I've built an OAD image for the CC2650 SensorTag containing the above buzzer update.

    Driving the buzzer at 4kHz works best for me.

    The below repository also contains the modified SensorTag_IO.c source file (hopefully TI won't complain on redistributing this file only) along with

    instructions on how to compile the firmware and generate the OAD image.

    https://github.com/cdealti/sensortag

    Regards,

      Cristiano

  • Thanks for your contribution. The information in github is really useful!