A few months ago, I purchased an old analog oscilloscope. Nothing fancy, just the basics I needed to get familiar with using a scope. I wanted to figure out how to use this piece of test equipment, and plus the glowing green screen and abundance of very clicky knobs looks (and feels) pretty cool.
In this post I will explain the basics of what an oscilloscope is, the difference between PWM and analog voltages, and how to create an digital to analog converter to create analog voltages with a microcontroller. With two analog signals, I will then draw vectors on an oscilloscope screen in order to display graphics and text.
What is an Oscilloscope?
An oscilloscope works by plotting a voltage over time. That way, you can very easily visualize signals. On older analog scopes, they actually deflect an beam of electrons to make a moving dot on a phosphorescent screen to create a line. But newer digital oscilloscopes still work in pretty much the same way. Oscilloscopes are a very important tool in electronics because they allow engineers and technicians to see the electrical pulses and signals that occur inside electric circuits, even when they occur very rapidly.
One cool example of an oscilloscope in use is visualizing an amplified audio signal. This makes a very sci-fi and robotic waveform, and lets you see how sound is made up of waves of varying frequency.
One of the problems I had after I got my oscilloscope was that I had no signals to measure! With an Arduino or other microcontroller platform, you can easily make a 0-5V square wave by pulling a pin high and low in a regular patter. This is somewhat interesting, but is not using the scope to nearly its full potential.
My Arduino Uno can also produce a PWM signal, (short for pulse-width-modulated signal). This means it can very quickly (in the MHz to high kHz range) go from 0-5V with varying duty cycles (amount of time 0V compared to amount on 5V). This shows up on my oscilloscope as a square wave that changes the width of time high.
This signal is produced by the following code:
for (int iii=0; iii<256; iii++)
Producing an Analog Voltage
A PWM signal can mimic an analog voltage by providing the same average power, but it isn’t truly an analog value. 50% 0V and 50% 5V doesn’t equal 2.5V, especially if your sample rate is high.
So, now we face a problem: how do we get an analog voltage from pins that can only produce 0 or 5V? A device that does this is called a DAC (Digital to Analog Converter). One way is to use capacitors to “smooth” a PWM signal. The goal is to choose a capacitor sufficiently large such that it takes more time than the width of the pulse to charge or discharge. This will produce a voltage that is between 0 and 5V depending on the duty cycle, but is also fairly slow, because it needs to allow the capacitor to charge and change its voltage.
Another option is to use a circuit composed of resistors connected in a particular way, called an R2R circuit. This is a very simple circuit that allows multiple binary signals to be converted into a single analog output.
It is called an R2R circuit because it only requires two arbitrary values of resistors; one simply needs to be twice the other. Thus, one is labeled R and the other two times R (2R).
One cool thing about this circuit is that you can make any voltage you want, and your precision goes up the more pins you go up. As you count up in binary (000, 001, 010, 011, 100, etc). The voltage produced at point A will correspondingly change. It worked really well for my project because:
- It’s fast: very little delay
- Easy to make: you only need two values of resistor (or one if you use two of the same in series where 2R goes)
- Cheap (because it is only made of resistors, which cost fractions of cents)
- Works well with Arduino: using the PORT functions you can quickly and easily write binary values to multiple pins at once, perfect for this application
Here’s a video that explains how this circuit works very well, using Thevenin’s superposition theorem to explain how to simplify the circuit:
After this circuit is put together, and the digital signals connected to an Arduino’s PORT pins, we can create analog signals. I started with a ramp, as it is a simple changing signal that can I can easily visually inspect with my oscilloscope.
Success! The circuit works, and now I can create quickly changing analog values with my Arduino Uno and a simple circuit of resistors.
Putting it all Together
The next step is to use the new ability to quickly create analog voltages to create the image we want on the oscilloscope screen. With two R2R circuits (one on the UNO’s PORTB and the other on PORTD), we can create two independent voltages simultaneously. With the oscilloscope on X-Y mode, the voltage on probe 1 controls the x-position, and the voltage on probe 2 controls the y-position. Therefore, it becomes possible to make the display “draw” lines by incrementing each value.
The first thing I displayed on my oscilloscope was a circle, because it is a simple combination of a sine and cosine wave. Here’s what each signal looks like. You can see the x and y component of the image, as two identical waves spaced 90 degrees apart.
Here’s another test image, this time one of a starburst. This is basically made up of ramps with periodic amplitude.
Now we want to be able to draw vectors on the display, so we can create an image out of points connected by lines. Basically, a connect-the-dots type of image.
Because the DAC we have contains 256 discrete steps, we can’t technically make any “smooth” line. A way to work within these constraints is common in computer graphics applications, as pixels often need to represent vector-based graphics. The code I’m using employs Bresenham’s line drawing algorithm to create a line between two given points with the function line() which has inputs of x1, y1, x2, and y2, as the start and end points of the vector.
And that’s the main idea of the code. With the coordinates of each vertex of an image, the code runs through each point and draws vectors between each point.
I started with the image of a logo I made a decade or so ago, this picture:
And then plotted a points to represent it with straight lines, within a 0 to 255 grid (because we have 256 steps of resolution).
And finally wrote down all these points and loaded them into an array that is programmed into the Arduino Uno.
Now if we want the logo to “spin”, the x-coordinates are changed in a periodic sinusoidal fashion to compress into a center line. If you want to see more information about how to do what I have described here, I recommend you watch the following videos:
Great Scott video:
In the first video, W2AEW goes over most if not all of everything that I have mentioned here. His code is at this link:
It was from his youtube video that I was inspired to mimic the idea of using an R2R circuit to create spinning graphics, and I am thankful for all of the interesting things I have learned along the way.