Dual Rotary Encoder Input For Power Supply Control

Hey everyone, I've seemingly jumped in way over my head for my Analog Circuits project at SCTCC. Now, I realize that my project is going above and beyond anything purely "analog" in nature, however that's not my main problem.

A little bit of description for my project: I have designed/am designing a digitally controlled power supply with 0 to +30V output at 0 to +1A. My project was originally inspired and is based around a circuit I discovered online (http://powersupplycircuit.blogspot.com/2009/07/mini-bench-power-supply-circuit.html) that is based around a quad operational amplifier. I have modified this circuit, since the original had limited capability (output to +15V) and also to make a digital interface. I am replacing the potentiometers that are controlling the output with a high voltage digital to analog converter (AD5504) with a serial interface. This chip is actually a 4 channel device, however I will only be utilizing two of the outputs, which are tied to the operational amplifiers to control output voltage and current limit. I'm designing this project to use a derivative of the ATMega8 (8, 88, 168, 328) to read user input via two rotary encoders, interpret the direction and displacement of the encoder, and increment or decrement the DAC output accordingly. The microcontroller will also be responsible for displaying the set voltage and current, with a separate panel meter to confirm actual versus theoretical output. The display will be an HD44780 type 16 character, 2 line display, which will update in the same action as updating the DAC output.

Some other, questionably significant specifications: The power comes from a transformer, which is tied directly to a full wave bridge rectifier, which is then in turn filtered by a 2200 microfarad capacitor. From there, a secondary capacitor, 100 microfarads, filters it further, and is then fed into an adjustable voltage regulator (some version of LM317 or similar) which has its output set for +30V. Connected in parallel to the voltage supplied to the adjustable regulator is a +12V regulator which will run a single or dual fan thermal management system. A +5V regulator is connected to the output of the +12V regulator, hopefully reducing thermal losses which may have been incurred by stepping down +36V to +5V. The +5V supplies the digital portion of the DAC, as well as the microcontroller and LCD displays. Each of the fixed regulators have 10 microfarad smoothing capacitors on their outputs.

The actual problem: In opting for a digital control scheme as opposed to the analog control of directly connected potentiometers, I am left with a problem of implementation. Now, this is all still in a development stage, and I have yet to attempt to hook everything up because I have limited supply of the high voltage DAC and the op-amp, which I foolishly decided to order in surface mount packaging. Apart from the problems I brought on myself with insufficient PCB manufacturing skills and inexperience in designing boards, I run into the problem of actually reading the input. Using two rotary encoders, one for voltage and one for current, was my original idea. However, wanting to limit the amount of polling that I had to do, in order to reduce the power consumption and increase the responsiveness of the interface, I began looking at an interrupt based control. Now, looking online I have seen several solutions for this, all with their own merit. However, seeing as the Arduino has two interrupt inputs, and I have two encoders to read, I thought to myself "How can I read four lines with two interrupts?" It has occurred to me to use basic digital logic to monitor the encoders. My idea, which I present to the community for consideration, collaboration, and critique is thus:

A three pin rotary encoder (A, B, Common) is connected with common to ground, A and B to digital pins on the Arduino. A and B are also connected as inputs to an OR gate, with the output of the OR gate connected to one of the interrupt pins on the Arduino. Using the same connections, a second encoder is connected to a separate OR gate, and separate digital input pins, with the OR gate output hooked to the remaining interrupt input. The Arduino monitors the interrupt pins, and when either is triggered, it polls the associated encoder to determine direction and number of pulses. From the input, it increments or decrements a 12 bit integer, which is then sent to the DAC for output to the op-amp.

That's basically all there is to it, any questions, comments, or concerns are welcome and VERY appreciated.


Maybe using pin change interrupts would help you: http://www.arduino.cc/playground/Main/PinChangeInt (and http://www.arduino.cc/playground/Main/PcInt)

Thank you for the helpful links! Unfortunately, it's all mumbo jumbo to me still. This will be my second microcontroller project ever, my first being a simple magnetometer which consisted of a linear hall effect sensor and the Arduino's analog input. My question is, is there some circuit using simple digital logic, including but not limited to gates or flip-flops, that would allow me to cause an interrupt if either of two pins change state? To further explain what it is I mean, I want to connect a rotary encoder to a logic circuit that will toggle its output whenever one or both of its inputs change state. So, for instance, if both channels of the encoder are high, and one goes low, the output of the logic circuit would change state. Is this possible?

You don't need to have both signals from a rotary encoder triggering the interrupts. Just have one signal trigger it and in the ISR (interrupt service routine) look at the other signal on a non interrupt pin and decide if you are going to increment or decrement your number. There is really no need to use interrupts anyway, you won't notice the difference if you just polled it.

If you must use external logic then you can get more resolution out of your encoder by looking at this:- http://www.thebox.myzen.co.uk/Workshop/Rotary_Max.html but I suspect it will be a bit too advanced for you.

A +5V regulator is connected to the output of the +12V regulator, hopefully reducing thermal losses

It makes no difference to the amount of power you burn off, it just spreads it over two chips.

If I only use one interrupt per encoder, won't I miss pulses? From how I understand it, and please correct me if I am mistaken, when I move the encoder one detent, only one of the signals will change. Thus if channel A is low and channel B is high, assuming clockwise rotation, only channel B will change state. Thus, if I monitor channel A for change, the microcontroller will miss the pulse since channel A did not change. If I decide that I should simply poll the inputs for change, will this limit the reliability? If I poll, for sake of argument, once per second. I turn the knob four detents in that one second, so the outputs start at (low, low) and change to (high, low), (high, high), (low, high), and then back to (low, low), it's now back to the original position and therefore the polling returns that no change has occurred, although four pulses have been missed. I am very limited in my knowledge, however I am attempting to understand.

won't I miss pulses?

No, if you trigger off each edge you will get exactly the number of pulses per revolution as the specification. Trigger off both signals and you get extra resolution just like I described in the hardware link.

If I decide that I should simply poll the inputs for change, will this limit the reliability?

No not if you poll fast enough.

If I poll, for sake of argument, once per second.

Good grief why would you want to do that. The arduino is doing precious little already what do you gain from delaying polling! You don't save any power, or processing ability, it just keeps on spinning just the same so you might as well do something useful with it.

Anyway does it matter if you miss a pulse, you are not counting them you are changing a voltage. Just like a mouse doesn't get every single pulse but you are using the feedback of the pointer so you just keep on pushing until you get to the point you want. You will just go on turning until you get the voltage you want. Only monitor one signal for a change, it is even more reliable if you monitor it for only one edge as there is no need to reverse the sense of the other signal to get the direction.

I'm very, VERY new to any microcontroller, so I simply assumed that I might be taxing the chip by polling too often. So, in theory, if I polled the rotary encoder pin at approximately 100Hz, this would be sufficient to read user input? Also, thank you for explaining the difference between interactive input and counting the pulses, I didn't quite understand when I read that it was acceptable to miss pulses. As some added information, I want to be communicating the set (or theoretical output) voltage to be displayed on an LCD using an 8 bit I2C I/O expander to control the LCD in 4 bit mode. The AD5504 digital to analog chip communicates over SPI, and I therefore have two separate protocols to manage at the same time. So, a simplified routine to call after either polling the encoder or receiving an interrupt and then polling for direction and displacement, would look like: The encoder state changes, the microcontroller reads this change, increments or decrements the 12 bit value, sends the value to the AD5504 via serial peripheral interface, sends interprets the 12 bit value as an analog value between 0 and 30V, stores this value as an integer, and sends this integer via I2C to the I/O expander, driving the LCD. Now, if that's all that needs to be done after an encoder is changed, is there any other useful things I can have the loop doing while waiting for input?

You will have more than enough time to do all that and still have a very responsive loop.

the microcontroller reads this change, increments or decrements the 12 bit value

Are you needing all that resolution? You don't say what the resolution of your rotary encoder is, I am assuming it is something like 16 PPR. Try and think how this is going to feel to a user. You are going to have him wind and wind and the voltage creep slowly up. Also you are putting out a voltage on the D/A into some analogue circuit and at the same time you are displaying the number you put out. What you want to do is to put out a voltage, then measure the output and display what you measure. That way the readings are always right and they always track correctly. Think of how it is going to start up? Is it always going to start at zero or some fixed value. Maybe you are thinking of starting up at the place it was before you switched it off? That would be nice but there are all sorts of complications knowing when to write the value to the EEPROM

Are going to display current as well as voltage? If so you will have to consider how that is done.

The encoder is rated for 24 pulses per revolution, and the output is going to be used as a lab/bench power supply. I'm going to use a digital panel ammeter and possibly a matching voltmeter to display the actual output voltage because I want to see how accurate my circuit is at setting and maintaining the voltage. The output will be tied to two binding posts, one for ground, one for +0~30VDC. I've also just had an idea to monitor the temperature of the MOSFET and voltage regulators using a temperature sensor or thermistor and output a pulse width modulated signal to a DC fan to keep the circuit running cool.

I'm into a similar project. Did you finally build this power supply? Would you share the changes you made to get more current?

You can save yourself a lot of trouble by using the quadrature library here in the playground (sorry no link, am posting from my phone). Rotary encoders can be maddening to work with.

Another option would be the quadrature decoder IC from avago. They are fairly pricey, about 9 usd, but a single chip would provide nice clean data from your two encoders with no microcontroller coding hassles.

The decision to buy vs build is always a factor in projects. I typically lean towards discrete solutions in my micro projects, as my time is a valuable commodity. IMHO nine dollars is an easy amount to justify; I will go the code route if the purpose of my project is to learn the low level details. Just because you CAN support a feature natively on the atmega/arduino does not always mean you MUST do so.