Introduction: Oscilloscope

Have you ever wanted to measure the pulse of a 555 timer circuit? Measure the pulse that a sound/music circuit is creating? Well, then you definitely need an Oscilloscope! "Oscilloscope or oscillograph or o-scope is a type of electronic test instrument that allows observation of varying signal voltages, as a two-dimensional plot of one or more signals as a function of time!" ~Wikipedia. However, o-scopes can get really expensive... So why do not we try to build one?

Step 1: Hardware That Is Required

You do not need much things the most important is an;

1x Arduino UNO Board

Arduino's analog pins can read up to 5V, which is pretty low for an O-Scope. So, basically we wanna lower the input voltage up to 5V. Programming the arduino to "do the maths" it can read the real voltage that we want to measure. The simplest and more efficient way to do this is a voltage divider. "A voltage divider is a passive linear circuit that produces an output voltage (Vout) that is a fraction of its input voltage (Vin). Voltage division is the result of distributing the input voltage among the components of the divider. A simple example of a voltage divider is two resistors connected in series, with the input voltage applied across the resistor pair and the output voltage emerging from the connection between them." ~Wikipedia. I want my O-Scope to be able to measure up to 14V.

Voltage divider resistances can be calculated by using this mathematical equation; Vout = R2*Vin/(R1+R2)

*Vout must always be 5V*

For example, if you want to make your O-Scope work with max voltage input set to 100V using the above equation then the R1 should be 19 times the R2. So if you are gonna use a 100Ω resistance as the R2 then the R1 MUST BE 1900Ω otherwise you could destroy your arduino board.

REMEMBER! THE HIGHER THE Vin THE MORE LOSS OF MEASUREMENT YOU WILL HAVE!

*Assuming that you wanna measure up to 300V (R1=59R2), however you are using the divider with a supply of 12V then arduino will recognize 0.2V, if you are using a 9V supply arduino will recognize 0.15V the difference is really small making the chances of mistakes on measurement more possible!*

Step 2: Arduino Programming

The arduino code is really simple! Basically, just open a serial port read the Vout from the voltage divider then using the equation from before make the arduino calculate the Vin. After that print the Vin on the serial port!

float vin = 0.0;
float vout = 0.0; float r1 = 180.0; float r2 = 100.0;

void setup() { //Put your setup code here, to run once: Serial.begin(115200); }

void loop() { //Put your main code here, to run repeatedly: vout = analogRead(A0) * 5.0 / 1024.0; //Read Vout vin = vout * (r1 + r2) / r2; //Calculate Vin Serial.println(vin); //Print Vin delay(500); // Delay }

Step 3: Visual Studio Programming (Setup/Libraries/Variables)

Things are becoming more complex... First of all, a library called Zed Graph is required to create the plot of the voltage on your computer screen. "ZedGraph is accessible as a control from the control toolbox in Visual Studio .NET. To access ZedGraph, first launch Visual Studio .NET, and create a new Windows Application (Forms) project. Open the form design so that it appears in the current window. View the toolbox using the View/Toolbox menu command. Right-click inside the "General" or "Components" sub-pane of the tool box, and select the "Choose Items..." option. Click "Browse...", and navigate to the ZedGraph.dll file. Once this file is added, you should see a ZedGraphControl option in the toolbox." ~Stack Overflow. After setting the library up we have to import it and every other library that we are going to use.

//Libraries
using System;
using System.Drawing; using System.Windows.Forms; using System.IO.Ports; using ZedGraph; using System.Globalization; using System.Diagnostics; //Variables

bool isPaused = true;
double vin = 0.00; GraphPane voltage = new GraphPane(); PointPairList voltageList = new PointPairList(); LineItem voltageCurve; double time;

Step 4: Visual Studio Programming (Form Design)

We need 4 things on our form;

1x "Zed Graph Control"

1x "Button"

1x "Serial Port"

1x "Timer"

Well that is all! Let's now configure the above items;

Button

Just let it as it is, we do not have to change anything on its properties!

Timer

Probably the easiest to configure just set the interval to 1000 and enable it!

Zed Graph Control and Serial Port

We are gonna configure them later on the coding side!

Step 5: Visual Studio Programming (Initializing)

We are now actually starting programming the code. The code is pretty simple so far, we are changing the background color of the graph, setting the dimensions of the button and the plot and calling the functions that will do the job!

public Form1() {
InitializeComponent(); this.KeyPreview = true; { zedGraphControl1.IsShowPointValues = true; zedGraphControl1.PointValueFormat = "0.00"; zedGraphControl1.GraphPane.Chart.Fill.Brush = new System.Drawing.SolidBrush(Color.Black); }; }

private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; serialPicker(); zedGraphControl1.Anchor = (AnchorStyles.Top | AnchorStyles.Right); zedGraphControl1.Dock = DockStyle.Top; button1.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right); button1.Dock = DockStyle.Bottom; graph(); }

Step 6: Visual Studio Programming (void SerialPicker())

Although this void looks huuuge, it is really easy to understand it! We are basically scanning every port from "COM1" to "COM7" if there is no arduino connected on these ports the the program prints the message "Connect your Arduino" and shutdowns to prevent exception crash.

void serialPicker() {
serialPort1.PortName = "COM1"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

try { serialPort1.Open(); } catch (Exception ex1) { serialPort1.PortName = "COM2"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); try { serialPort1.Open(); }catch (Exception ex2) { serialPort1.PortName = "COM3"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); try { serialPort1.Open(); }catch(Exception ex3) { serialPort1.PortName = "COM4"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); try { serialPort1.Open(); } catch (Exception ex4) { serialPort1.PortName = "COM5"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); try { serialPort1.Open(); } catch (Exception ex5) { serialPort1.PortName = "COM5"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); try { serialPort1.Open(); } catch (Exception ex6) { serialPort1.PortName = "COM6"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); try { serialPort1.Open(); } catch (Exception ex7) { serialPort1.PortName = "COM7"; serialPort1.BaudRate = 115200; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.Handshake = Handshake.None; serialPort1.RtsEnable = true; serialPort1.ReceivedBytesThreshold = 5;

serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); try { serialPort1.Open(); } catch (Exception ex8) { MessageBox.Show("Connect your Arduino"); Application.Exit(); } } } } } } } } }

Step 7: Visual Studio Programming (void DataReceivedHandler())

We need a void to read the input of the arduino! The same void is going to add the time and the voltage input to our graph void as well!

public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
SerialPort sp = (SerialPort)sender; string indata = sp.ReadExisting(); Debug.Print("Data Received:"); Debug.Print(indata); if (!isPaused) { if (indata.Contains(".")) { vin = double.Parse(indata, new CultureInfo("en-US")); voltageList.Add(new PointPair(time, vin)); voltage.XAxis.Scale.Max = time; voltage.AxisChange(); zedGraphControl1.Refresh(); } } }

Step 8: Visual Studio Programming (void Graph())

This void is actually configuring the "Zed Graph Control" and finally adding the curve on the oscilloscope screen!

private void graph() {
voltage = zedGraphControl1.GraphPane; voltage.Title.Text = "Oscilloscope"; voltage.XAxis.Title.Text = "Time (s)"; voltage.YAxis.Title.Text = "Voltage (V)"; voltage.YAxis.Scale.Min = 0; voltage.YAxis.Scale.Max = 14.00; //Change it on the max voltage that your O-Scope can read voltageCurve = voltage.AddCurve(null, voltageList, Color.LightGreen, SymbolType.None); voltageCurve.Line.Width = 3; }

Step 9: Visual Studio Programming (Button/Timer)

This is the last part of the code there are not many to explain this part is really simple by its self!

private void button1_Click(object sender, EventArgs e) {
isPaused = !isPaused; }

private void timer1_Tick(object sender, EventArgs e) {
if(!isPaused) time++; }

Step 10: Finally, the Testing!

I want to measure the pulse that a 555 timer circuit is creating... Damn... I wish I had an oscillosc- wait a second! We just built one! As you can see it is working just fine! However the 555 timer circuit is generating a mix of a square, a triangle and a sawtooth wave, so it needs to be changed, I could never understand the problem if it had not been for the oscilloscope!