====== Digital to Analog ====== Following the last lab, you've probably wondered how we can take signals from a digital device and translate them into something that an analog circuit can use. When would you want this? Well, it turns out that playing 1s and 0s from a speaker doesn't sound so good. Motors, electromagnets, and lights are also typically things you want to have more fine control of than just turning on or off.
[[https://docs.google.com/document/d/1mOxo64BMLNHk7mMz566ctJnvJPSbJwiu9l17Wd1mqKk/copy|Lab Template]]
=== PWM === We'll start with the simplest option: Not actually converting to analog. How can this work? For things that care about the average of an input over time! If you toggle an LED between on and off quickly enough (a few hundred times a second), it just looks like it is on but dimmer. Some motors also can sometimes be controlled this way, as they'll keep spinning due to inertia when the power is off. And if we vary the relative amount of time an output is on or off, we get even finer control. This technique is know as ''P''ulse ''W''idth ''M''odulation or ''PWM''. We'll start here with a pair of humble LED circuits, shown below:
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:led_for_pwm.png}} | | Basic circuits for testing LEDs |
* Use your power supply to set $V_{in,1}$ to be between 3 and 4V for your first circuit. * Set up a 0-5V square wave with your function generator and connect it to $V_{in,2}$. * This is not the same thing as a 5V PkPk square wave! You need an offset. * Scroll down in the function generator options until you get to the ''duty'' option. * Use your scope to measure the two input voltages * ''Meas''ure the average voltage of $V_{in,1}$ * ''Meas''ure the average voltage of $V_{in,2}$ Adjust the ''duty'' percentage until the average voltages match. Check if the product of 5V * the duty cycle (as a percent) reasonably matches your power supply's voltage setting. In practice, people should adjust the duty cycle in 10% increments at most. If they want too, they can use their DMM's analog reading of $V_{RMS}$ to assess if the voltages match. While this works for a surprising number of situations, there are some limitations. One is that you'll always be rapidly switching voltages, which can cause unwanted oscillations elsewhere in a larger design. Some devices also don't appreciate being switched on and off quickly, and will let you know by dying. As a practical limit many microcontrollers can only output a few mA of current; transistors are your friend in such instances. ===== R-2R ladder ===== Okay, maybe you need to have something that does better than being the same voltage on average. One way of doing this is essentially the inverse of the successive approximation method we used last week. Consider the circuit below to the left:
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:r-2r_ladder.png}} | {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:r2r_total_thevenin.png}} | | A 3-bit R-2R ladder | The Thevenin equivalent circuit |
Each of our digital inputs can take on values of either 0V or 5V. So, how do we analyze this? The answer is that we treat it like a series of voltage dividers. If all of the inputs are off, there's not going to be current anywhere, so $V_{out} = 0V$. Let's separate the last part of the circuit and analyze it via Thevenin's theorem.
How does that work? The equivalent series resistance is 2R and 2R in parallel, which is just R. The series equivalent voltage is $V_{in,0}/2$, where $V_{in,0}$ is either 0V or 5V. Let's use this info to redraw an equivalent circuit:
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:r2r_last_stage.png}} | {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:r2r_last_stage_thevenin.png}} | | An isolatable part of the R-2R ladder. | The Thevenin equivalent of the circuit |
From here, we can immediately combine the two resistors in series to an equivalent of 2R. Then, we have another voltage divider circuit. This one is a 50/50 split between $V_{in,0}/2$ and $V_{in,1}$. Our four possible outputs for the four different combinations of these inputs are 0V, 1.25V, 2.5V, and 3.75V. If you want more precision, add more stages. Each new input improves the resolution by a factor of 2.
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:r2r_next_stage.png}} | {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:r2r_next_stage_thevenin.png}} | | The next stage of the circuit, drawn with the equivalent for the first stage | The equivalent circuit for the second stage. |
Build the R-2R ladder shown previously, and test that you get (approximately) the expected outputs as you change the inputs. Note that the inputs should be either at ''0'' (0V) or ''1'' (5V). This may be easiest to accomplish by connecting a long-ish wire to each input and moving the far end to a rail hooked up to either 0 or 5 volts. You probably didn't notice it at the time, but the UChicago Black Box(tm) that we used in the first lab? That used an 8-bit version of this circuit.
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:blackboxladder.png}} | | The conversion circuit used in our mystery function generator. Note that we explicitly are using only one value of resistor, but place two in parallel to achieve half the resistance value. Why? It looks neat, and it makes it so that you don't have to worry about what resistors go where if they're all the same.|
====== Dedicated DAC chips ====== We'll be using a ''TLC7528C'' chip for our digital to analog conversion today. It uses this same R-2R topology to do its conversion. This chip was chosen in part because it has eight parallel inputs, making it so we once again don't need to worry about encoding a sequence of values in time. Let's take a look at the chip's pins now:
| {{:phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:dac_chip.png?400|}} | | A pinout for the DAC chip. This one is large enough we didn't need an adapter. |
The relevant groups of pins are as follows: == Outputs == Pins 2 and 20 serve as a pair of outputs that can be toggled, letting you use one set of controls to update a pair of outputs. This is why there are ''OUTA'' and ''OUTB'' connections. This particular chip is designed for the outputs to be analog currents, but we'll use a different mode == Grounds == Pins 1 and 5 are listed as ''AGND'' and ''DGND'' respectively. While there is some subtlety to the need for different grounds for analog and digital parts of a circuit, that is a problem for another course entirely thankfully. == Feedback == Pins 3 and 19 are for feedback resistors (''R''esistor ''F''eed''B''ack ''A''/''RFBA'' and ''RFBB'') used for tweaking the behavior of the R-2R ladder. == References == Pins 4 and 18 are reference voltages, which in our case will be the outputs we're using for the device. == Controls == Pins 6, 15, and 16 are used to select different behaviors of the chip. ''6'' toggles which output is being updated. ''15'' is the ''C''hip ''S''elect (''CS'') pin, used to communicate that the chip should be ready to capture a new set of inputs. ''16'' is the ''WR''ite pin, used to start the conversion of the current digital inputs to analog. The bar over the top of the lettering denotes that the logic is inverted, i.e. setting pin 16 to 0V will constantly update the output, and 5V will stop updates. == Digital Inputs == Pins 7 through 14 are the digital inputs, from most to least significant bit respectively. The most significant bit is the one with the greatest impact (i.e. toggling it will increase the output by **half** of its total range) whereas the least significant bit will only increase the output by a factor of $\frac{1}{2^8}$ of the range. == Power == Last but not least, pin 17 is used for powering the chip $V_{DD}$. This particular model needs some overhead; if you power the chip with 5V the maximum analog value out seems to be only around 4V. However, the accepted digital inputs depend on this voltage as well, and at +15V it will not recognize the outputs of the Pi Pico. ===== Testing the DAC ===== To start out, we'll use some switches as our inputs to our DAC, and read out the output on the scope.
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:dac.png}} | | Our circuit for using the DAC. Note that ''NC'' means ''N''ot ''C''onnected. You should use the dedicated can use the two connections on the far right side of your power supply for the +5V here, you'll need the adjustable ones later. |
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:switch_config.png}} | {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:8_switch.png?300px}} | | Our circuit for controlling the inputs to the DAC. The exact value of the resistors doesn't matter here, their job is just to make sure that the pins are at zero volts when the switch is open. | The physical switch module. You may want to use a ballpoint pen or a pencil to actuate the switches. | | {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:rainbowwire.png?0x200px}} || | A connected set of jumper wires, which you can use to make connections from your switches to your chip a little more cleanly. Yours have been split into groups of 10, and the sequence is the same used for resistor color coding. ||
Build and test the circuit, observing the output on the oscilloscope. Please be careful with these chips, as it is easy to bend their legs due to their length. You can use chip extractor (which looks like a little set of tongs) to remove them, or gently wedge a screwdriver under the length of the chip to pop it out of the board. ---- ==== Using your output ==== Right now, even though you can read a voltage from the output, it isn't much use for powering anything. Its capabilities max out around 10mA of current, which will barely light an LED. This looks like another job for a follower!
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:follower.png}} | | A lovely ''LF411'' follower circuit for your LED viewing pleasure. Note the +-10V rails. If we use 15V, then the threshold for the DAC to register a value as a ''1'' is too high to use with the Pi Pico later. |
Add your follower to the end of the signal chain and experiment with your switch inputs. ==== Using digital devices for digital things ==== It makes more sense for us to maybe use a computer here, so that we can dynamically change the inputs at a decent speed. For this, we're going to use a Raspberry Pi Pico running MicroPython. This isn't a course on coding, so we've got a basic program already in place. If you know Python, you'll be able to dig through what it is doing a bit. Connect the pins of your Pico to the digital outputs of your ADC as shown below
| {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:pico_pinout.png}} | {{phylabs:lab_courses:phys-226-wiki-home:digital_to_analog:dac_with_pi.png}} | | How to connect the pico's pins to the DAC. The ribbon cable should already be set up on the pico side of things, if not then pay attention carefully! We skip pin ''3'' because it is connected to the pico's ground, but we use pin ''8'' later to connect to the circuit's ground. The white wire is unused. ||
After connecting the device, plug the Pico's USB cable into the lab computer. With this, the Pico will start outputting a 100Hz sine wave that the DAC will interpret. Use your oscilloscope to observe the output of your DAC. Use the other channel of your oscilloscope to observe a 100 Hz sine wave from the function generator. If you want to affect what it's doing, you'll need to send commands yourself. Open the ''Thonny'' application, and click on the hamburger menu in the lower right corner. Select ''MicroPython (Raspberry Pi Pico) ยท Board CDC @ COM##'' where ''##'' is some number that depends on your machine. After doing this you should see the "shell" window on the bottom of the application update to the following: MicroPython v1.28.0 on 2026-04-06; Raspberry Pi Pico with RP2040 Type "help()" for more information. >>> If the pico ever becomes unresponsive, you can restart it simply by removing the USB cable on the PC side and plugging it back in. You'll need to use the bottom-right menu in Thonny to re-connect after doing this. You can now alter the outputs by adjusting the following wave properties: ''offset'' from 0 to 1 ''amplitude'' from 0 to 1 ''freq'' ''func'' as one of ''sine'', ''pulse'', ''gaussian'', ''sinc'', ''exponential'', or ''noise'' ''pars'' which depends on the function. for a ''pulse'', there are three parameters corresponding to risetime, uptime, and falltime for ''gaussian'' the width is affected for ''sinc'' the scaling is affected for ''exponential'' the decay time is affected for ''noise'' the distribution characteristics are affected. Up the frequency of the output to 200 Hz. You can do this by entering ''wave.freq = 200'', pressing return, and then typing ''refresh()'' Verify that the outputs on the scope properly update. Switch to a square wave, by entering the following commands: ''wave.func=pulse'' ''wave.pars = [0,.5,0]'' ''wave.amplitude = .25'' ''wave.offset = .25'' ''refresh()'' The output should be a 2.5V pk-pk square wave at 200 Hz. Test the limits of your setup to determine what the smallest registerable change in amplitude is. Note that the ''wave.amplitude'' is expressed as a percentage of the maximum, so you'll want to make Since 1 is a full scale change, $ 1/(2^8-1) = 0.004$ is the smallest percent change we can expect to see from an 8 bit system. This comes out to 19 to 20 mV or so for a 5V scale. {{page>phylabs:lab_courses:phys-226-wiki-home#Assignments&nodate&nouser&noheader&inline&nofooter}} ---- That's it for the experiment, though you can feel free to experiment a bit with the Pico to generate different outputs or to hook up a speaker to the op-amp (inline with an appropriate resistor to not deafen your labmates).