Using an LED driver to read buttons

November 11th, 2015

The boss wants to add some lighted pushbuttons to an aircraft-specific bezel, and I don’t want them to be hand-wired forever. But each cluster of lights is physically isolated from the main processor board, and I don’t have much space. So I’d like to drive the LEDs and read the buttons with as few parts as possible, and I’d like to communicate reliably over a few inches of ribbon cable. Also, I’d like current control over the LEDs, which is my usual modus operandi these days. (There are two clusters: one has two lighted buttons, the other has four.)

I could just stick a Cypress processor on each board, I’ll have lots of control. But even the QFN-56 isn’t as small as I’d like. It’s square, and a rectangular shape might be “skinny” enough to fit where a square of the same area may not. Also, no current control. Also, the Cypress part isn’t very good at driving things.

A few years ago, before I started working with the TLC5929 and TLC5923, I’d discovered an I2C-connected part that had global current control, and global and individual PWM control, of 16 LED outputs: the TLC59116. I’d started to design it — or at least, thought-experiment it — into several projects I had going at the time. In the end, I abandoned it. But it occurred to me that I could use four outputs for the LEDs, and then four more as multiplexer drivers; I could use one spare I/O pin to read the results, two pins for the protocol, plus power and ground.

To cut this down from epic proportions: after several weeks of design, testing, experimentation and one online forum conversaion with a TI engineer, I’ve got a working design. But I’m not multiplexing the buttons as I originally thought of.

Button board prototypeThe problem with multiplexing the buttons is that once I sent a message to change the outputs, I’d have to wait for the message to travel and be acknowledged. The delay isn’t the problem so much as linking the multiplex read with the end of the transmission, especially given that other transmissions would be happening. Actually, in retrospect it wouldn’t be that big of a deal, especially since I ended up with a considerable amount of the work happening in a state machine anyway. But I found a solution I like better.

This part includes a set of error bits: one per output. For each output that is active (trying to drive an LED or other load), the corresponding bit tells whether the output is in thermal overload or has no load. Trying to overload the output has issues I shouldn’t even have to begin to tell you, starting with the fact that I probably won’t be driving the actual LEDs hard enough for the button outputs to overload even across a dead short. (…This was actually tested until the TI engineer figured out what I was trying to do.) But the absence of a load? That I can work with.

The bit turns on if a) the output is on and b) the output has a reasonable load. It turns off if there’s no load. The no-load error condition is self-clearing, so I can simply poll the part. Since I can read up to all 16 error bits with a single read, I can simply read the status over and over as quickly as possible. Which turns out to be something over 600 times per second (assuming two connected boards), giving an opportunity to do some debouncing.

Turns out I’ll also want control over the TLC59116 reset lines; if the I2C bus gets locked up I want to be able to clear it. So that extra I/O pin is useful, but not as a multiplex input.

It was a lot of work, and finishing it will be even more, but this is a definite win. Also, the part comes in an SOP package, and I arranged my resources such at it left 8 pins (4 on each side) free at one end of the chip. Means it won’t need traces there, giving a little more room.

Current Mirror: epilogue 3

July 20th, 2015

Hah, we’re not finished yet…

It seems that between unreliable connections on the breadboard and a bad solder joint on one of the FETs (that one is clearly my own fault), I was getting faulty results from my experiments. I discovered this when I started swapping transistors around — specifically, the input with one of the outputs.

So in response I soldered the FETs into little stackable modules.
Stackable FET modules

Obviously I’m planning to use a minimum of three FETs on the output, but I wanted flexibility while minimizing the number of connections.

And… oh, look! Suddenly I’m getting decent stats with five output FETs and slightly over 20mA input. Also, if you look at the photo above, you’ll notice that I’m using two 120 ohm, 1210 resistors in series. Previously I was looking at two 360 ohm, 2512 resistors in parallel as I was uncomfortable with how hot the 120s were getting. 240 ohms limits me to 40mA, but that’s not a problem any more, the resistors are much cooler and take less space.

It seems I was correct that there are diminishing returns to the input:output ratio, but they’re not as bad as they seemed. And that’s assuming, of course, that there aren’t more problems with my breadboard that I haven’t seen. But this is close enough, gets me just about the results I was shooting for, and at most I might have to tweak REXT (I’m thinking of using 2k for 24.8mA per output) or tweak the calibration somewhat. Or both.

Current Mirror: epilogue 2

July 1st, 2015

More experimentation. The mirror isn’t perfect; I’m actually getting closer to a 3.32:1 ratio using six transistors on the output, 3.3:1 with five, 3.15:1 with four and 2.55:1 with three. Adding more output transistors to reach my nominal goal works, but I’m getting rather diminishing returns.
Six transistors output, not that efficient.

On the other hand, adding output transistors increases my maximum output amperage. Three seems to peak at around 91mA (with a 42mA input), but with six I can exceed 94mA (with a >28.5mA input). After some more crude experimenting it’s starting to look like diminishing returns above four transistors, which give me about 93.6mA output at about 39mA input.
Four transistors on the output give a better balance.

If I can dedicate two outputs of the LED driver they only need to be about 20mA each, which is more in line with the rest of my needs for that driver. The current mirror is obviously not very efficient as a multiplier, but it’s good enough for my needs with a bit of adjustment.

Current Mirror epilogue: Living Without

June 11th, 2015

One of the fundamental issues driving the need for the current mirror (see previous two posts) is that the clock and backlighting circuit share a common ground, and all the current control drivers I can reasonably lay my hands on are low-side drivers (connect between the load and ground). It won’t do to “dim” the clock! So there’s no way to make the TLC5923 directly drive the clock backlights.

…Except maybe it can. If you paid attention during the last post you’ll notice two facts:

  • The backlight is too dim to see below about 25mA. Actual cutoff TBD, but it’s safe to say that below 10mA might as well be turned off.
  • The clock circuit itself only draws around 6mA. Certainly below 10mA.

…with the one caveat that we’re talking specifically about the Davtron M800 clock. If we ever use a different clock, the rules may change. (But then, that’s true of the backlight as well.)

But assuming we’re sticking with the M800, that’s what we’ve got. So what if I do this:

Common ground driver circuit

Common ground driver circuit: this is totally cheating.

If I always keep the related TLC5923 outputs energized to at least the current draw of the clock (plus whatever the backlight draws at that level), the clock will run as long as CLK_PWR is energized. Since the range of the backlight drops to “invisible” well above the clock’s “on” state, it allows me the full range of the backlight while still giving me full power on the clock.

The two high-side transistors then allow me to individually control on/off power to the clock and the backlight.

The only drawback I can see is that turning the clock on will provide the backlight with an extra 6mA or so of power. On the other hand,

  • 6mA isn’t a lot. It probably won’t be noticeable.
  • People rarely turn off the clock.

Honestly, the current mirror seems less of a kludge to me. But I should be able to use this. On the other hand, if we ever change the clock, or if Davtron changes to (say) a 25mA LED backlight that dims all the way down, then this circuit will fail. The current mirror will continue to work, though we might want to remove most of the output transistors.

Current Mirror Deuxième Partie

June 10th, 2015

OK, well. Part of the problem with the previous circuit is that the LED driver ends up dropping nearly 12v at 100mA. My test device was getting rather toasty.

After some more research (read: poking around Google) I discovered that if I wire multiple transistors together, the input-to-output current changes in direct ratio to the number of parallel transistors on the input side to the number of parallel resistors on the output side. So a total of six transistors allows me to drive the input at 20mA and end up with a 100mA output.

While losing the capacitor, resistor and two opto-isolators of the older circuit saves some board space, using those huge 2A FETs is a bit of overkill that I certainly don’t need. So I poked around and found some much, much smaller P-channel FETs with sufficient specs for the job. In fact, after seeing them first hand, I decided (with input from Phil) that they in fact may be a bit too excessively small.

BSS84AKMB 50 V, single P-channel Trench MOSFET

I wanted small, I got small.

Aside from other handling problems, Phil noted an issue with components of this size being particularly susceptible to tombstoning. Anyway, I found an alternative part in SOT23 that would do the job and not make Phil pull his hair out. As he pointed out, even six SOT23 transistors would actually take up less real estate than the crap it was replacing, so it would be a win either way.

The BSS84AKMB and the BSS84,215

The BSS84AKMB vs. the BSS84,215

SOT23 breakout boardWith that in mind I got a parcel of the BSS84,215 parts and a handful of breakout boards from eBay and built myself the updated circuit. The result works well and the TLC5923 isn’t getting hot.

So now I’m looking at possibly adding a current-limiting resistor in series with the LED driver output to further mitigate stress on the part, but at least I’ve got the circuit I need. From here the most it needs is some fine tuning. It also turns out that the clock itself only draws a few milliamperes (less than 10mA), so the new part is more than adequate as a replacement for the NDT2955 we’ve been using for everything, saving even more real estate.

Current Mirror/Multiplier Breadboard

My Current Mirror/Multiplier Breadboard. Fake bread, real board.

Meantime, it seems that the backlight is too dim to see for about the bottom ¼ of the output range, but that’s OK. I can scale the incoming values appropriately; I proved that while writing the code to drive the amplifier version of these, where you have to calibrate both the low and high range to make it work right.

Current mirror/multiplier circuit

P.S. I’m a little bothered by the fact that I seem to have the source and drain swapped. From what little I know about FETs… well, I honestly am not sure I know what I’m doing. But the circuit works. I’m going to poke around some more regarding this and see what I come up with.

Current Mirror

April 16th, 2015

So over the last few years I’ve been trying to get quiet control over the brightness of various backlights and indicators on our various bits of hardware. By “quiet” I mean “not PWM” because PWM ends up generating EMI, which was causing power supply problems and interfering with some unshielded monitors and, in one case, a bargraph display. Eventually I came up with either one of two Texas Instruments parts, depending on the application: a TLC5929, which I can substitute for the STP16CP05 already designed into many of our projects; or a TLC5923, which gives me more control but has a different footprint. These two parts allow me to control their current outputs programatically at run time, where the STP16CP05 only has a reference resistor and on/off control.

So that takes care of backlights and many individual indicators. It does not affect multiplexed displays (I may write more on that later), and I can’t use it to control the backlights of a Davtron clock module we use in many places. That’s because the clock module has three parts tied to a common ground, but the LED drivers are low-side, which means they drive to ground. Sort of like Open Collector but with current control. If I try to use the TLC part to dim the backlight, it also ends up also reducing the voltage to the clock (and the alarm, but we don’t use that).

On one hand, I actually don’t need to control the clock backlight beyond “on” and “off”, which I can do with a transistor and an opto-isolator. On the other hand, I’d like to be able to, and I’ve taken it as a sort of personal challenge. It turns out the clock backlight is an incandescent that draws about 100mA at 12v, so those are the specs I have to work with.

PWM is an obvious possibility. I worry about sending switching 12v@100mA through nice, thin wires next to switch inputs when we drive the clocks in some yokes, unusual though that is.
One problem is that we’re using a pull-up resistor to shut off the driving FET, so there’s a slew rate problem. I countered that by adding a second opto-isolator on a separate output (but tied to the first, and inverted) to force the Gate high. I also added a resistor-capacitor pair to try to filter the signal, with partial success; apparenly the inrush current was too much for the resistor, even after we moved to the next higher wattage. The result was an ugly kludge that I mislike.

I tried finding a high-side, run-time programmable current controller, but they’re rather thin on the ground. Most of the suitable ones I found are obsolescent. This isn’t the answer.

For my next trick I did some experiments and calculations and determined that changing the pull-up to a 243Ω resistor would allow me to use the FET as a — get this, it’s really radical — as a transistor. I drive the gate low directly from a TLC5923 output and use the combination of the drive and the resistor as a divider network. It gives me a range of about 5 to 7 values out of 127, but it works. But it may require individually calibrating each unit, and it operates on a curve. (We won’t know until we have a few more units manuafactured; as of this writing I only have the prototype and a single manufactured unit). Hardware-wise it’s simpler, but now the firmware is ugly and possibly the installation as well.

In the last couple weeks I’ve done numerous searches for current buffers, current mirrors and current amplifiers. I’ve narrowed the search to two circuits: one opamp-based current amplifier and one FET-based current mirror. The advantage of the amplifier is the ability to use a single TLC5923 output to drive it; the drawback is that a suitable opamp that will drive sufficient current is on the expensive side. I suppose I can add a transistor follower to boost the power but the Analog side of the Force is not strong with me. The mirror circuit is very simple and only requires two transistors, but I could only find a high-side source-to-low-side load, which is exactly the opposite of my needs. Also, it will require that I drive 100mA from the LED driver, which means tying multiple TLC5923 outputs together. Not an egregious problem but it does tie up more resources, possibly also forcing me to adjust the reference resistor for more power — which in turn requires me to lose resolution on other outputs. This depends on the exact application, of course, and how many outputs driving how much current are already in use.

I can’t seem to find the opamp-based amplifier I came up with, but here is the FET-based current mirror:

As I said, it was upside-down. So I turned it over:

What can I say at this point except that it appears to work? I have a prototype running at my desk even as I write this. Even without heatsinks the transistors are warm, but not hot to the touch. I have been able to control the clock backlight from zero to full brightness. There don’t appear to be any downsides to this beyond those I’ve already mentioned.

Most importantly, this is appears to be a fairly simple way to make a low-side current driver drive a high-side circuit. I haven’t tested beyond this application, and that not very much, so I can’t actually say how good it is, but this appears to work.

And now I have one more tool in my bag of tricks.

Am I back? Only time will tell.

April 16th, 2015

It’s been almost four years since my last post (not counting the SOPA stuff). I’d like to say I’m going to start posting again, but I’m not sure. It’s not that I have nothing to say; but much of it is likely rants about problems with development platforms, and then there’s the fact that I’ve been feeling pretty numb — and uninspired — since my wife left. Also, a lot of what I might otherwise say would either be obvious, or about programming in general, or about hardware. I suppose none of those is a bad thing per se. It’s just what I get for making the theme of the blog so specific.

I guess I’ll go with the flow. A lot has happened at work since I last posted, so I guess I should talk about that.

Note: I’ve enabled comments on this post, for now. Let’s see how quickly the spam gets overwhelming. I suppose an argument can be made for moving this to the actual Wordpress site, since a) they keep their software up to date and b) presumably they exercise spam mitigation.

Stop SOPA/PIPA: Blackout Day

January 18th, 2012

A number of sites are blacking out today in protest of SOPA/PIPA. Another large number are adding banners or making other obvious visual changes. I decided not to bother on this site, because my readership is so low (zero, I think).

I liked this video so I figured I’d throw it in:

Some sites that are blacking out today:

Rep. Lamar Smith is claiming that this is just a “publicity stunt” on Wikipedia’s part. Really? A publicity stunt? How does Wikipedia have such a low profile that they need publicity? The MPAA is calling Wikipedia out for being “irresponsible”. My favorite comment on this story (and there are a lot!) points out MPAA’s hypocrisy very simply:

Taking down the websites of others = Not abuse
Taking down your own website = Abuse

Stop American Censorship points you to a number of other places like SOPA Strike and Fight for the Future and SOPA Countdown.

And more. I may update this as I find more and as time permits, but I do have to get some work done. Still, look around a bit and you’ll find tons of examples of people protesting this bill.

Lamar Smith and the other proponents are, of course, trying to play it down and pretend it’s just a few malcontents and losers, and that anybody who opposes the bill are just dirty pirates, rather than people with legitimate concerns about our freedoms.


January 11th, 2012

Today we’re going to take a break from my usual mind-numbing war stories and take a political stance. I prefer to leave politics out of this blog, but these acts promise to destroy my blogs, many other blogs, and uncountable other web sites. Its purported purpose: to help protect artists’ work and incomes. The actual purpose: to enrich a few legacy middle-men.

It probably doesn’t matter anyway; nobody is reading this blog except spammers’ ‘bots, and maybe a friend or two.

I could pontificate for hours on this subject, if I had the energy. I’ll try to keep it succinct.

  • The proponents claim this is aimed at massively infringing foreign sites, but the language in the acts is very vague. All attempts to change the language to narrowly target massively infringing foreign sites have been met with overt hostility and stonewalling. This, if nothing else, tells me that the language is vague deliberately in order to specifically allow abuse after it’s passed.
  • The DMCA takedown provisions and other laws are being abused now. If you think SOPA/PIPA won’t be, I’m sorry, but you’re living in a dream world.
  • These laws are more about killing off competition than preventing copyright infringement, despite what claims are being made.
  • This will not promote innovation, which is why Copyright and Patent laws were created in the first place. This will stifle it. What we need in this economy is more innovation, not less. We also don’t need companies shut down because their only other choice is to go broke defending themselves in court, or to spend all their profits fighting court cases instead of, say, building products and selling them. And using the profits to grow, and hiring people.
  • SOPA/PIPA won’t stop infringement. It may encourage it, as people realize that almost anything they do will infringe, and they lose all respect for IP laws.
  • These laws are being drafted and promoted by politicians who not only are completely ignorant of what the Internet really is and how it works, but they are proud of their ignorance. What’s more, they are ignoring all the voices raised against these laws and claiming that nobody is protesting. Well, nobody important.
  • Many, many clever and intelligent people are strongly opposed to these laws, including some who would personally benefit. Including a few surprises. The fact that so many people with so many diverse points of view are protesting these laws, while only a few support it, should say something in itself.

There’s more, but it’s been discussed many times in many places better than I can express it in a brief blog post. I just wanted to speak up, and point you to a resource or two. First I’m going to post a copy of Jane Wells’ excellent post on this subject. Jane is the UX lead for Wordpress. I’m probably violating copyright by doing this but I doubt Jane will mind; this will help get the word out, and I’m giving proper attribution and pointing back to the original. (And Jane, if you see this and object, please just let me know. I’ll remove the copy and just leave a link.)

I was in two minds about making this post until I saw Jane’s. But since I use Wordpress for free, I figured that somehow I owe it to them to lend active support to their position. (That plus the fact that I agree with them.) So without further ado:

You are an agent of change. Has anyone ever told you that? Well, I just did, and I meant it.

Normally we stay away from from politics here at the official WordPress project — having users from all over the globe that span the political spectrum is evidence that we are doing our job and democratizing publishing, and we don’t want to alienate any of our users no matter how much some of us may disagree with some of them personally. Today, I’m breaking our no-politics rule, because there’s something going on in U.S. politics right now that we need to make sure you know about and understand, because it affects us all.

Using WordPress to blog, to publish, to communicate things online that once upon a time would have been relegated to an unread private journal (or simply remained unspoken, uncreated, unshared) makes you a part of one of the biggest changes in modern history: the democratization of publishing and the independent web. Every time you click Publish, you are a part of that change, whether you are posting canny political insight or a cat that makes you LOL. How would you feel if the web stopped being so free and independent? I’m concerned freaked right the heck out about the bills that threaten to do this, and as a participant in one of the biggest changes in modern history, you should be, too.

You may have heard people talking/blogging/twittering about SOPA — the Stop Online Piracy Act. The recent SOPA-related boycott of GoDaddy was all over the news, with many people expressing their outrage over the possibilities of SOPA, but when I ask people about SOPA and its sister bill in the Senate, PIPA (Protect IP Act), many don’t really know what the bills propose, or what we stand to lose. If you are not freaked out by SOPA/PIPA, please: for the next four minutes, instead of checking Facebook statuses, seeing who mentioned you on Twitter, or watching the latest episode of Sherlock*, watch this video (by Fight for the Future).

Original post here, and please direct your replies there, as she has a lot more visibility than I. Or you can follow Mike Masnick’s excellent Techdirt blog, or read more at Torrentfreak. Or any of dozens of other sites.

Just to make a point: this isn’t about allowing infringement. This is about excessive, over-broad laws intended only to prop up an obsolete business model at the expense of our freedoms and our well-being. There are other ways to deal with copyright violations besides these.

Generating a 921,600 baud clock on a Cypress PSoC 1

June 5th, 2011

I had some other programming philosophy thing I wanted to post here after the last one, but I can’t remember what it was. So I figured I’d share some of the neat tricks I’ve learned over the years. Here’s one.

Lantronix XPort

A few years ago I was working with some Lantronix XPort devices. These are nifty little modules that let you connect a serial port to Ethernet. They cost about US$50 each, and for simple designs can save tons of development time. (You can also use their developer kit to make custom designs.)

We were using them as shipped, only changing the settings. The thing is, they only use standard baud rates, from 300 bps to 921600 bps.

Standard baud rates are a pain in the neck to derive from normal CPU clocks, which tend to use nice, even numbers in the millions with lots of zeros. The Cypress PSoC 1, for example, has a 24,000,000 Hz system clock. Now, you could add an external 7.3728 MHz oscillator to your design, but that just drives the cost up more. We didn’t want to do that.

I mentioned 7.3728 MHz specifically because the Cypress UARTs require an input clock of 8 times the bit rate. And therein lies the problem: your fastest clock on the Cypress is 48 MHz (SysClk*2), but you need to divide by 13 to get (close to) your nominal bit rate, and 48÷13 gives you ≈3.692 MHz. Right around half what you need.

Well, my colleague came up with a clever way around this. The only drawback is that it uses some resources you may not be able to spare. Fortunately we were using CY8C29466 parts, which have lots of digital blocks.

  • You need two digital blocks for this baud rate generator.
  • You need two adjacent output rows.
  • You need an input row corresponding to the lesser of the two output rows.
  • You need a Global Output column and its corresponding Global Input column, and they must correspond to the lesser of the two output rows.

Plus of course you need a digital block for the transmitter and another for the receiver. If you’re doing full duplex on a 4-block part such as something in the 24xxx series, you’ve just run out of digital blocks.

Here’s what you do:

  1. Place two 8-bit PWM blocks.
  2. Set them both thus: Clock=SysClk*2, Enable=High, CompareOut=(two adjacent output rows), TerminalCountOut=None, Period=12, PulseWidth=6, CompareType=Less Than, InterruptType doesn’t matter (I set to Terminal Count by habit), ClockSync=Unsynchronized, InvertEnable=Normal. Note that I actually set the second PWM’s PulseWidth=5 but it’s not critical. It’s going to be asymmetrical either way.
  3. Click on the Digital Interconnect for the lesser of the output rows you chose (the one that’s closer to the top of the page). Now set the LogicTable Select to A_XOR_B and set the output to whatever Global Output column you chose.
  4. Click the Global Output, set the Interconnect to OutputToInput.
  5. Click on the Digital Interconnect for the corresponding input row. Select the input column you just interconnected. Set the synchronization to Async.
  6. Place your serial parts. Set the clock input to the input row you just set up. Set ClockSync to Sync to SysClk*2.

You should end up with something like this. Click on the image below to see the full size.

Screenshot of PSoC Designer page for 921,600 bps generator

Now comes the tricky part. When you enable the PWMs in your code you need to make sure their output timing overlaps. I don’t know what it would take in C, but in assembly it’s a matter of adding NOPs between the two macro calls until the output does what you want.

    nop                    ; NOPs take 4 cycles each. I just stuck in 2 for illustration.
    nop                    ; I don't actually remember how many I added to make it work.
    PWM8_2_Start_M         ; This is an OR REG[expr],expr which takes 9 cycles.

I was never able to make the output work properly by calculating the exact timing; I always had to fiddle to get it right. You might have more luck. Or skill. The important thing is that they be out of phase, and the transitions happen at different times. Also that once it is written into the code the number of CPU cycles between start statements is fixed; once it works, it will work every time.

The easiest way to check is, of course, to temporarily (or permanently if you like) hook the generated signal to an output pin and attach an oscilloscope. If you were to view all three signals you might see something like this. (I did this in Excel, of course; I don’t have access to my original ’scope data. The actual signals would never look so clean.) Click on the image to see the full size.

Overlapping 460.8k inputs and a 921.6k output

Overlapping 460.8k inputs and the 921.6k output you get by XORing them

The actual amount of overlap is not critical. Obviously it will never be symmetrical, but it goes through a ÷8 process in the UART anyway. The important thing is that the output is twice the frequency of the inputs.

It’s pretty clever, and I’m not even bragging — it was my colleague’s idea. I just made it work.