1
\$\begingroup\$

I'm trying to control a few servos and a bunch of RGB-LED from an arduino board. To do that I'm going to chain together a few TLC5940 chips. The issue I'm trying to resolve at the moment is what PWM settings do I need for the servos; particularly what are the min rotation and max rotation settings?

My servo is a: HiTech HS-55. This site: http://www.servocity.com/html/hs-55_sub-micro.html says the servo runs on "+Pulse Width Control 1500usec Neutral" with a 600us pulse being -90 and a 2400us pulse being +90.

To figure out how to generate pulses that long with my PWM driver I need to know the frequency the driver runs on. The data sheet for the driver: http://www.ti.com/lit/ds/symlink/tlc5940.pdf says this about the PWM operation on the bottom of page 19:

The grayscale PWM cycle starts with the falling edge of BLANK. The first GSCLK pulse after BLANK goes low increases the grayscale counter by one and switches on all OUTn with grayscale value not zero. Each following rising edge of GSCLK increases the grayscale counter by one. The TLC5940 compares the grayscale value of each output OUTn with the grayscale counter value. All OUTn with grayscale values equal to the counter values are switched off. A BLANK=H signal after 4096 GSCLK pulses resets the grayscale counter to zero and completes the grayscale PWM cycle (see Figure 21). When the counter reaches a count of FFFh, the counter stops counting and all outputs turn off. Pulling BLANK high before the counter reaches FFFh immediately resets the counter to zero.

Unfortunately I don't have any idea what that means. (I think) I know that the PWM driver gets some form of clock signal from arduino but unfortunately doesn't help me figure it out.

Can anybody help me figure out what settings I need to use on the PWM driver to generate the desired pulses. The closest value will work. For my application if the servo gets within a couple degrees it should be close enough. Will this even work at all? My understanding of how servo's work is that they generally need a pulse every 20ms so even if I calculate how to generate the correct pulse duration I doubt it will magically work out to a pulse every 20ms. Will the servo accept the input?

\$\endgroup\$
  • \$\begingroup\$ Can you clarify a bit the relationship between the TLC5490 and the servos, if there is any... \$\endgroup\$ – angelatlarge Apr 17 '13 at 16:43
  • \$\begingroup\$ There is no relationship. I just need to be able to control a large number of LED's and Servo's from an Arduino Uno board. \$\endgroup\$ – William Apr 17 '13 at 21:00
2
\$\begingroup\$

To answer the TLC5940 side of the question:

First of all, bear in mind that when using TLC5940 your intensity need not be 12-bit values (4096 values): you can use the TLC5940 using with intensities of any value 12 bits or less. For instance, 8-bit intensities (256 values) do provide a very satisfying result. More on this latter.

Assuming 12-bit intensities, here's how GSCLK and BLANK work: TLC5940 doesn't have its own clock. So GSCLK is used to figure out when to turn on and off each LED. At the beginning of a cycle, all LEDs are on. Each time positive-going edge on GSCLK is received an internal counter is incremented on TLC5940. Each LED whose intensity value is lower than the counter is turned off. So LEDs with intensity 1 are turned off after the first cycle, LEDs with intensity 2 are turned off after the second cycle, and LEDs with intensity 4096 are not turned off at all. At the end of the cycle the chip does not reset itself, rather it expects a positive-going edge on BLANK to reset it, and after this the cycle begins again.

Here's what this means for driving the TLC5940: you need two PWM outputs; one for GSCLK and one for BLANK, and the one for BLANK needs to happen every 4096 cycles of GSCLK. Now notice that we are talking about the frequncy here, and not the duty cycle, whereas it is the duty cycle that analogWrite() controls. To drive the TLC5940, you could use a library written for driving TLC5490, or you can do the lower-level driving of TLC5940 yourself, which can use one of the following approaches (assuming you are using an ATmega-based Arduino, and in scale of increasing difficulty):

  • Program the two timers yourself such that they use different prescalers such that the BLANK line is driven at 1/4096th the frequency of the GSCLK
  • Program the CKOUT fuse on the ATmega, causing it to output the clock signal on one of its output pins. Use this for GSCLK. Then use a timer to generate a BLANK pulse at 1/4096th of clock frequency.
  • Clock the ATmega externally, and use the same clock for GSCLK. Have an ATmega timer generate the BLANK pulse at 1/4096th of clock frequency.

Now to the question of frequency relationship between the TLC5940 clocking and the PWM. The BLANK line will have a duty cycle of 1/4096 (or whatever the maximum intensity value you are using), so that probably will not work for your servos. The GSCLK is usually 50/50 duty cycle but need not be. Lets assume that you want your LEDs to appear to be steady, and lets take the flicker theshhold to be 50Hz. This would mean that you need your intensity 1 LED to be flickering at 50Hz or above, meaning that a 4096-clock long cycle should complete in 20 milliseconds, meaning that your GSCLK clock should be at least 204kHz. At 204kHz the clock pulses are about 5uS long. So while in theory you could use the same clock for your servos and the TLC5940 (I think that's what you are asking): if you maintain the clock frequency (at 204kHz) and change the duty cycle you could control your servos and clock the TLC5940. However, if you use 12-bit intensities, then the greyscale clock needed by TLC5940 is going to be too fast for the servos.


But, if 4096 intensity values is too much to handle, consider using 8-bit intensity values. You will still have to send them as 12-bit values (that's what the TLC5940 interface expects), however, the is no law that says that your BLANK pulse must occur every 4096 GSCLK clocks. If it occurs every 256 clocks, you have yourself 8-bit intensity. So your 8-bit intensities should be sent as valid 12-bit values (with the high four bits being zero), and you'll restart the clocking cycle every 256 clocks. You can use any other number of intensity bits, as long as it is 12 or less, in the same manner. If you are using 256 intensity (=greyscale) values, then your minimum clock is 12.8kHz, and the clock duration is 78uS. Closer the 2400uS +90 pulse, but still quite far away. If we assume that +90 pulse is 90/10 duty cycle, then we calculate the clock cycle length to be 2.6mS, which translates into 375Hz clock. At this clocking, the maximum intensity value that will yield no flickering is 8 values (3 bits) at 50Hz persistence theshhold, and 16 values (4 bits) at 25Hz. You can decide whether that is good enough for your purposes.

\$\endgroup\$
  • \$\begingroup\$ Wow this is an impressive answer. I think there is all the information all need in here to figure out if I can get it to do what I want but I'm going to have to read it a few times to understand it. Thank you for the help! \$\endgroup\$ – William Apr 17 '13 at 21:01
  • \$\begingroup\$ I was just looking at the TLC library for Arduino and it actually has a method for controlling servos from the library. So it looks like all this work has been done for me (hopefully). Thanks again. \$\endgroup\$ – William Apr 17 '13 at 21:53
1
\$\begingroup\$

You have a grayscale clock input (recommended is 30 MHz, see page 3), and it counts through 4096 values.

For your servo that is much too fast (the cycle length is ~140µs), so you need to use a slower clock. Then you can compute the timing of the servo signal in terms of your clock cycles.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.