TLC5940 change PWM frequency

Hello

I'm using a tlc5940 to controll 12 LED channels. Works great but one problem. There is a significant buzz when dimming LEDs. Does anyone know how I can increase the pwm frequency in the tlc5940 library?

Hardware configuration:
Arduino MEGA 2560 with tlc5940 pwm shield from sparkfun. on the pwm shield two 6 channel led driver shields.

regards Maik

There is a significant buzz when dimming LEDs.

Where is this coming from? It is not something you can cure by altering the frequency of the chip it is an over all circuit fault with the thing producing the buzzing.

IT comes from the Led driver. The Led driver is from ledsee.com.
Do you think its a Hardware Problem? I just thought increasing frequency would solve the problem.

Buzz is normally caused by ceramic capacitors. Try adding some more of them between Vcc and GND near the driver inputs.

IT comes from the Led driver.

What from the TLC5940?
I think not. Normally it is inductors. It can come from capacitors but it should not come to that because you should have better decoupling capacitors, large electrolytics as well as the small ceramics.
The chip itself does not make a noise, I have used them in dozens of projects and never a peep out of them.

The buzz comes from the Led driver. I use the TLC5940 only for generating the pwm Signals for the Led driver. I thought that increasing this pwm frequency oder 2 kHz would help that I don't hear that buzz anymore. I would test it but don't know how to change it or at what frequency the pwm signal currently is.

Can you explain what you mean by LED driver or better still have a link to it. There is no need to use anything else but this chip to drive your LEDs.
Changing the frequency is not easy and would involve hacking the libary , and would probbly not fix things either.

This is the Led driver shield I use. I need this for using high Power LED s. On each Channel are seven 3w leds. Voltage is 24V dc

Thanks, it makes a lot more sense now. Those black round things are inductors, that is coils of wire. It is those that are making the noise as the windings repell and attract each other when the current changes.
It is likely that the ringing is not related to the driving frequency but are some sort of resonance effect in the coils.
What driving libary are you using?

I only use the TLC5940 library for dimming each channel.
http://playground.arduino.cc/Learning/TLC5940

I simply use this code for Dimming (in this case 4095 means LEDs off)

Tlc.set(0, 4095); 
      Tlc.set(1, 4095);
      Tlc.set(2, 4095);
      Tlc.set(3, 4095);
      Tlc.set(4, 4095);
      Tlc.set(5, 4095);
      Tlc.set(6, 4095);
      Tlc.set(7, 4095);
      Tlc.set(8, 4095);
      Tlc.set(9, 4095);
      Tlc.set(10, 4095);
      Tlc.set(11, 4095); 
  
      Tlc.update();

The buzz is only significant when LEDs are almost off e.g. at value 3000.

The LED shield supports up to 50kHz PWM frequency.

There is a config file for the library:

/*  Copyright (c) 2009 by Alex Leone <acleone ~AT~ gmail.com>

    This file is part of the Arduino TLC5940 Library.

    The Arduino TLC5940 Library is free software: you can redistribute it
    and/or modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    The Arduino TLC5940 Library is distributed in the hope that it will be
    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with The Arduino TLC5940 Library.  If not, see
    <http://www.gnu.org/licenses/>. */

#ifndef TLC_CONFIG_H
#define TLC_CONFIG_H

#include <stdint.h>

/** \file
    Configuration for the Arduino Tlc5940 library.  After making changes to
    this file, delete Tlc5940.o in this folder so the changes are applied.

    A summary of all the options:
    - Number of TLCs daisy-chained: NUM_TLCS (default 1)
    - Enable/Disable VPRG functionality: VPRG_ENABLED (default 0)
    - Enable/Disable XERR functionality: XERR_ENABLED (default 0)
    - Should the library use bit-banging (any pins) or hardware SPI (faster):
        DATA_TRANSFER_MODE (default TLC_SPI)
    - Which pins to use for bit-banging: SIN_PIN, SIN_PORT, SIN_DDR and
        SCLK_PIN, SCLK_PORT, SCLK_DDR
    - The PWM period: TLC_PWM_PERIOD (be sure to change TLC_GSCLK_PERIOD
        accordingly!)

    How to change the pin mapping:
    - Arduino digital pin 0-7  = PORTD, PD0-7
    - Arduino digital pin 8-13 = PORTB, PB0-5
    - Arduino analog pin  0-5  = PORTC, PC0-5 */

/** Bit-bang using any two i/o pins */
#define TLC_BITBANG        1
/** Use the much faster hardware SPI module */
#define TLC_SPI            2

/* ------------------------ START EDITING HERE ----------------------------- */

/** Number of TLCs daisy-chained.  To daisy-chain, attach the SOUT (TLC pin 17)
    of the first TLC to the SIN (TLC pin 26) of the next.  The rest of the pins
    are attached normally.
    \note Each TLC needs it's own IREF resistor */
#define NUM_TLCS    1

/** Determines how data should be transfered to the TLCs.  Bit-banging can use
    any two i/o pins, but the hardware SPI is faster.
    - Bit-Bang = TLC_BITBANG
    - Hardware SPI = TLC_SPI (default) */
#define DATA_TRANSFER_MODE    TLC_SPI

/* This include is down here because the files it includes needs the data
   transfer mode */
#include "pinouts/chip_includes.h"

/* Set DATA_TRANSFER_MODE to TLC_BITBANG and change the pins below if you need
   to use different pins for sin and sclk.  The defaults are defined in
   pinouts/ATmega_xx8.h for most Arduino's. */

#if DATA_TRANSFER_MODE == TLC_BITBANG
/** SIN (TLC pin 26) */
#define SIN_PIN        DEFAULT_BB_SIN_PIN
#define SIN_PORT       DEFAULT_BB_SIN_PORT
#define SIN_DDR        DEFAULT_BB_SIN_DDR
/** SCLK (TLC pin 25) */
#define SCLK_PIN       DEFAULT_BB_SCLK_PIN
#define SCLK_PORT      DEFAULT_BB_SCLK_PORT
#define SCLK_DDR       DEFAULT_BB_SCLK_DDR
#endif


/** If more than 16 TLCs are daisy-chained, the channel type has to be uint16_t.
    Default is uint8_t, which supports up to 16 TLCs. */
#define TLC_CHANNEL_TYPE    uint8_t

/** Determines how long each PWM period should be, in clocks.
    \f$\displaystyle f_{PWM} = \frac{f_{osc}}{2 * TLC\_PWM\_PERIOD} Hz \f$
    \f$\displaystyle TLC\_PWM\_PERIOD = \frac{f_{osc}}{2 * f_{PWM}} \f$
    This is related to TLC_GSCLK_PERIOD:
    \f$\displaystyle TLC\_PWM\_PERIOD =
       \frac{(TLC\_GSCLK\_PERIOD + 1) * 4096}{2} \f$
    \note The default of 8192 means the PWM frequency is 976.5625Hz */
#define TLC_PWM_PERIOD    8192

/** Determines how long each period GSCLK is.
    This is related to TLC_PWM_PERIOD:
    \f$\displaystyle TLC\_GSCLK\_PERIOD =
       \frac{2 * TLC\_PWM\_PERIOD}{4096} - 1 \f$
    \note Default is 3 */
#define TLC_GSCLK_PERIOD    3

/** Enables/disables VPRG (TLC pin 27) functionality.  If you need to set dot
    correction data, this needs to be enabled.
    - 0 VPRG is not connected.  <em>TLC pin 27 must be grounded!</em> (default)
    - 1 VPRG is connected
    \note VPRG to GND inputs grayscale data, VPRG to Vcc inputs dot-correction
          data */
#define VPRG_ENABLED    0

/** Enables/disables XERR (TLC pin 16) functionality to check for shorted/broken
    LEDs
    - 0 XERR is not connected (default)
    - 1 XERR is connected
    \note XERR is active low */
#define XERR_ENABLED    0

/*  You can change the VPRG and XERR pins freely.  The defaults are defined in
    the chip-specific pinouts:  see pinouts/ATmega_xx8.h for most Arduino's. */

#if     VPRG_ENABLED
/** VPRG (TLC pin 27) */
#define VPRG_PIN        DEFAULT_VPRG_PIN
#define VPRG_PORT       DEFAULT_VPRG_PORT
#define VPRG_DDR        DEFAULT_VPRG_DDR
#endif

#if     XERR_ENABLED
/** XERR (TLC pin 16) */
#define XERR_PIN        DEFAULT_XERR_PIN
#define XERR_PORT       DEFAULT_XERR_PORT
#define XERR_DDR        DEFAULT_XERR_DDR
#define XERR_PINS       DEFAULT_XERR_PINS
#endif

/* ------------------------- STOP EDITING HERE ----------------------------- */

#if DATA_TRANSFER_MODE == TLC_SPI
/** SIN (TLC pin 26) */
#define SIN_PIN        TLC_MOSI_PIN
#define SIN_PORT       TLC_MOSI_PORT
#define SIN_DDR        TLC_MOSI_DDR
/** SCLK (TLC pin 25) */
#define SCLK_PIN       TLC_SCK_PIN
#define SCLK_PORT      TLC_SCK_PORT
#define SCLK_DDR       TLC_SCK_DDR
#endif



#if !(DATA_TRANSFER_MODE == TLC_BITBANG \
 || DATA_TRANSFER_MODE == TLC_SPI)
#error "Invalid DATA_TRANSFER_MODE specified, see DATA_TRANSFER_MODE"
#endif

/* Various Macros */

/** Arranges 2 grayscale values (0 - 4095) in the packed array format (3 bytes).
    This is for array initializers only: the output is three comma seperated
    8-bit values. */
#define GS_DUO(a, b)    ((a) >> 4), ((a) << 4) | ((b) >> 8), (b)


#if VPRG_ENABLED
/** Arranges 4 dot correction values (0 - 63) in the packed array format.
    \see setDCtoProgmemArray */
#define DC_QUARTET(a, b, c, d)   ((a) << 2) | ((b) >> 4), \
                                 ((b) << 4) | ((c) >> 2), \
                                 ((c) << 6) | (d)
#endif

#endif

I think I have to change these values:

#define TLC_PWM_PERIOD    8192

#define TLC_GSCLK_PERIOD    3

But I don't really uderstand how to use it.

I found an explanation of it:

That means that the formula for TLC_PWM_PERIOD is:

TLC_PWM_PERIOD=f OSC / (2*f PWM)

f OSC is freqency of the Arduino ->16MHz

In my case I need 20kHz that you wouldn't hear anything:

TLC_PWM_PERIOD = 16000000Hz / (2 * 20000Hz)
TLC_PWM_PERIOD = 400

The formula for TLC_GSCLK_PERIOD :

TLC_GSCLK_PERIOD = ((2 * TLC_PWM_PERIOD) / 4096)-1

for me it has to be 0 beacuse it has to be an integer value

The question is if 400 is a valid value for it.

Changing TLC_GSCLK_PERIOD (make it bigger) will change the PWM frequency but 400 is way too big.

By default it's 3. Making it 6 (for example) will halve the PWM period.

Are you sure?
When I see the formula then changing TLC_GSCLK_PERIOD to 6 will decrease the frequency.

I said 400 for TLC_PWM_PERIOD and 0 for TLC_GSCLK_PERIOD.

I have tested it but doesn't work. Dimming the LEDs doesn't work anymore with these values :frowning:

Sorry, I meant "double".

Setting it to 6 will halve the frequency, double the wavelength.