Saturday, April 13, 2019

Arduino Logic--when Op Amps become (N)op(e)-Amps

There has to be a pun in there somewhere? Just got a new Arduino based synth module working, which I call "Con Brio Gate". It makes gate patterns that speed up or slow down.

I'll give out details about that gizmo in an upcoming post, (update! post is here) but I feel I learned an important lesson during fab which I wanted to share with ya'all. Maybe this post will help me remember next time?

Goes like this:

Don't try designing audio circuitry during the occasional 20 minutes between work meetings.You'll rush your design and end up getting a long, nasty visit from the kludge fairy. 

OK with that Epiphany out of the way, how about another tidbit, and the crux of today's biscuit:

Don't use op amps where transistor logic will work!

Word??

What I was trying to do: get incoming gate signals (for my setup, that's 0-5V DC) conditioned to feed Arduino I/O digital pins. I wanted to use a single TL084 for everything: buffering incoming analog CV (which is easy, and works--see the zener fragment below) but also use the same IC to condition incoming and outgoing logic (0V-5V, but nothing in between--and certainly nothing greater than 5V DC--see the I/O voltage limits for Arduino here).

Since I was trying to "just handling logic"--ons and offs--how hard could this be? Figured it'd be easy.

I used a LM324, the oldest/cheapest quad Op Amp I had in my junk box, of course.

First problem: most op amps don't go all the way to the low rail (0V in my case, which is logic LOW for my circuit) or all the way to the high rail (15V in my case; but I wanted 5V out--logic HIGH). In my initial design, I completely blew this detail out my, well, you know.

Right away, not going all the way down to 0V we have problems. We want to go from 0V to 5V, not 2V to 4V or whatever. The result was that ghd Arduino wouldn't "fire" on logic low.

Sooo....this op amp comparator in my conbrio design didn't work (obvious eh?)--what was I thinking?

For Arduino logic applications, I cannot recommend this fragment, at all, ever! 

Another problem with the above circuit fragment: the Arduino doesn't want to see 15V at any I/O pins--that sort of high V might fry something. As I draw it here, when the op amp, used as a comparator, flips "high" it goes closer to 15V than 5V and we don't want that.  Easily fixed with a voltage divider (200K/100K) but it was just dumb to not think through this with a bit more clarity.

Here's another link  that describes Arduino IO voltage and current limitations in case you missed the last one....

And for output buffering, the next fragment didn't work either! Again the voltages needed don't go down to 0V or up to 5V.  Same lack of clarity while reasoning this out. Very nice!

For me the output was between about 3.5V and 5V, not the 0V-5V needed.  Doh!


Using zeners and voltage dividers to clamp things is possible, but arguably adds complexity:

This works OK for analog signals, but to get to 0V you probably need a V- rail vs. ground.  I often use -15V for the V-- rail, 1K for the resistor on the right, and a 5V zener for analog.  Probably not worth the trouble for digital logic.

Transistors to the rescue! This simple NPN transistor fragment seems to always work, every time. Yes, you can use FETs for this, lots of variations, but I had a big bag of about 300+ 2N3904's so that's what I used.



This is easy jr. high school electronics! R1 and R2 form a simple voltage divider that will determine the voltage when current flows inward through the 10K resistor.  So, for for 5V at output when IN is LOW, and your rail is 15VDC try 200K and 100K for R1 and R2 respectively.

When you populate your fragment like that, the input signal can be pretty anything above about .7V relative to ground. Once you saturate the transistor you are good to go; the output will go from the voltage divider value to ground. Yeh!

This is true I/O: No problem if the input signal feeding the transistor base is the Arduino digital I/O pin, or if the output of this fragment feeds a digital input of your Arduino. Both configurations work and offer simple buffering and protection.

And yes, this fragment will invert the incoming signals' logic, but who cares?  You're writing the code, Elmo--HIGH and LOW can do whatever you want--so code accordingly!

Another benny: When this fragment is used to buffer an Arduino digital output signal, there is no 40mA current sourcing limitation you normally get with an Arduino pin. If you pick the wattage ratings of your R2 and R1 resistors correctly you can go hog wild--it's like you have the utility company working for you--since the Arduino is only sending its current through the transistor's base, and not to some current-hungry stage down the road, for almost every audio application, using this fragment, you're good to go.

OK I didn't follow this advice, trying to get clever with my single LM324. I didn't blow up my Arduino (good since it was soldered into my mistake-laden PCB), but I did get a long and nasty visit from Kristy Kludge, the kludge fairy, with his unshaven legs, bad hairdo, and wicked halitosis:

The tell tale signs of a visit from the Kludge Fairy: perf boards, ugly solder, dremel tool cuts, etc. Smells like kludge spirit!

As an old bandmate of mine always said, it was real, it was fun, but it wasn't real fun. Next time, I'll plan my design a bit more carefully.  I hope.


Preview: The ConBrio Gate design on my stale of the art (circa 1973) breadboard setup. Works--but no buffering yet!

OK that's it for now. Soon I'll reveal the Con Brio circuit, complete with its approx. 15 (?) kludge fixes. This one was so close to being tossed aside for a complete refab it's silly, but I made it through somehow. Update: done and works. Post is here.

And always remember: what doesn't kill you makes stronger, and also, more confused!  See ya!

No comments:

Post a Comment

A guy OK with C tries to learn C++. Bjane me Up, Stroustruppy!

Why no posts so far for 3-2024?  I have been woodshedding, brushing up on C++ skills.  What got me to finally start digging into C++? I was ...