This instructable will show you how to build a portable Touch Screen
Oscilloscope for less than 40 U$!

The oscilloscope is one of the most powerful electronic instruments that
is available to electronics hobbyist, experimenters, and engineers. It is
mainly used to measue time-varying signals. Any time you have a signal
that varies with time( slowly, quickly, and /or periodically ) you can use
an oscilloscope to measure it , visualize it, and to find any unexpected
features in it.

We can use an oscilloscope to observe and study signal characteristics
that we could otherwise not see .

You will learn about the Arduino mega analog to digital converter( ADC).

We will be using the Arduino analog A0 input to sample and capture time
varying signals by Writing a program that will also display those signals
in a 3.8" TFT LCD touch display, and we will input data to modify the
oscilloscope behavior, using the touch capabilities of the screen display.

Before we start building and programming, lets review some basic
characteristics of an oscilloscope.

These are functions you can control on most oscilloscopes:

Sweep speed. Sweep speed is usually measured in units of time per distance,
like milliseconds/centimeter or milliseconds per division.This might also
be referred to as the horizontal sensitivity.

Vertical sensitivity. That's the measure of how sensitive the display dot
is to voltage applied to the input terminals. It is usually measured in
volts/centimeter or volts per division.

A trigger signal can be generated when the signal value reaches some
particular level - the trigger level. In most cases you can set the trigger
level to a voltage value of your choosing. A trigger is used to capture and
stabilize the waveform on the screen, or to wait for an event before
capturing the data
The oscilloscope, like my 4 channel DC DVM, will not be as accurate as
a commercial unit, but it works pretty good for low voltage and low frequencies.

Step 1: UPDATE: Sketch to Convert Oscope to 3 Channel DVM With Graphic Display + Lego Enclosure

Thank you to all who voted for me! This Instructable won 3rd prize in the Arduino contest, and first prize in the Gadget contest...

Included are pictures and code to convert your oscope to a 3 Channel DVM and to show the output of each channel individually in the scope display by pressing a soft key on the display. ( the third button from the top)

you will need an L shaped female pin connector if you want to have the flexibility of inserting jumpers, otherwise, just bend the pins on one side of the jumpers to insert them in the analog channels (A0- A3) to use them as your probes.

Just download the sketch and upload it to the Arduino.

You can label each channel individually, just change the wording in the sketch.

I have also made a lego enclosure for the scope..check out the pictures.

Step 2: Parts List

You will need :

Step 3: Build the Hardware.

Construction of the Oscilloscope is fairly simple. You just have to put the parts of the Sainsmart kit together. All you need to do is add two jumpers; one for ground, and the other to use as  your oscilloscope test probe.

You will need to bend the pins on one side of the jumper wires, and insert them into the A0 pin and GND pin of the Arduino (see pictures for detail),  before installing the display shield, as the display shield will cover the ports once it's in place. 

Plug  the Shield into the Arduino ,  then plug  the display into the shield, and you're done!!! 

Now let's  test the display before we turn it into an oscilloscope.

Step 4: The Software: UTFT Library Test.

If you finished putting your kit together, plug it into the USB cable that connects to your PC running the Arduino IDE.

If you haven't done so, download the UTFT and UTouch Libraries, and copy them to the libraries folder where you have the arduino IDE installed.

If the libraries installed properly, you will see the UTFT and the UTouch options when you click on the Files option, and scroll down to examples.

If the UTFT option is in your menu list, select it, then select arduino, and finally, UTFT_Demo_320x240. This will load the cool demo program.

With the program loaded in the IDE, scroll down to view the following code:

 // Uncomment the next line for Arduino 2009/Uno
//UTFT myGLCD(ITDB32S,19,18,17,16);   // Remember to change the model parameter to suit your display module!

// Uncomment the next line for Arduino Mega
UTFT myGLCD(ITDB32S,38,39,40,41);   // Remember to change the model parameter to suit your display module!

Comment out the command for the UNO , and uncomment the  command for the Mega ,as I did.

Now, go to the tools menu, click on board, and select  Arduino Mega 2560 or Mega ADK , if not already selected.

Click on verify to compile the program. If there are no errors, click on upload to  load and execute the program.

If everything is Ok, you will see a cool demo program running. Pictures in this step, show screenshots of the demo running.

Step 5: The Software: UTouch Library Test.

Now we need to test the Utouch  Library

Go to the files menu  and select ; Examples>UTouch>Arduino>Utouch_ButtonTest and load the program to the IDE.
Verify and  run the program.

You should see a keypad show up in the display, and, as you press the number keys, they should show up at the bottom of the screen.

If all went well, we are ready to load the Oscilloscope software.

Step 6: The Oscilloscope

Below, you will find the sketch for the Oscilloscope. Before we copy and paste the program, let's review some limitations and explain the program.

I've had to do a fair amount of research to come up with the code, and many snippets have been "borrowed" from several sources.

I divided the program into several subrutines to make it easier to understand. The code is well documented, but, if you have trouble understanding it, leave a comment and I'll try to explain it.

The Oscilloscope bandwidth is limited to about 1 khz, but there is room for improvement.

The input is limited to a 5volt peak to peak waveform, unless you use a voltage divider at the input, and also limited to positive waveforms from 0 to 5 volts.

I used some code I found at: http://www.microsmart.co.za/technical/2014/03/01/advanced-arduino-adc/ to adjust the ADC sample time.

The graphics and touch functions were modified, and borrowed, from the Henning Karlsen examples provided in his libraries.

I used a LM 317 voltage regulator, and a 555 IC timer as an astable ocillator, to create the signals used to test the oscilloscope input.

Hope you enjoyed reading and hopefully building this instructable. If you find it useful, please vote for me in the contests.

Note: I included the sKetch, the UTFT and the UTouch libraries in the libraries.zip file for those of you having trouble.

Copy and paste the sketch to your Arduino IDE

//----------------------START PROGRAM
Program: OscopetouchLCDmega

Description: Digital Oscilloscope with data displayed
on Color TFT LCD with touch screen

Hardware: sainsmart mega2560 board with 3.5" tft lcd touch module display and shield kit

Software: Developed using Arduino 1.0.3 software
This program requires the UTFT library and the
UTouch library from Henning Karlsen.
web: http://www.henningkarlsen.com/electronics
Version 1.00
Date: 5 April 2014

Author: johnag

// Declare which fonts we will be using
extern uint8_t SmallFont[];
// Initialize Screen and touch functions
UTFT myGLCD(ITDB32S,38,39,40,41);
UTouch myTouch(6,5,4,3,2);
// Declare variables
char buf[12];
int x,y;
int Input = 0;
byte Sample[320];
byte OldSample[320];
int StartSample = 0;
int EndSample = 0;
int Max = 100;
int Min = 100;
int mode = 0;
int dTime = 1;
int tmode = 0;
int Trigger = 0;
int SampleSize = 0;
int SampleTime = 0;
int dgvh;
int hpos = 50; //set 0v on horizontal grid
int vsens = 4; // vertical sensitivity

// Define various ADC prescaler
const unsigned char PS_16 = (1 << ADPS2);
const unsigned char PS_32 = (1 << ADPS2) | (1 << ADPS0);
const unsigned char PS_64 = (1 << ADPS2) | (1 << ADPS1);
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);

//------------Start Subrutines------------------------------------
//--------draw buttons sub
void buttons(){
myGLCD.setColor(0, 0, 255);
myGLCD.fillRoundRect (250, 1, 310, 50);
myGLCD.fillRoundRect (250, 55, 310, 105);
myGLCD.fillRoundRect (250, 110, 310, 160);
myGLCD.fillRoundRect (250, 165, 310, 215);
//-------touchscreen position sub
void touch(){
while (myTouch.dataAvailable())
if ((y>=1) && (y<=50)) // Delay row
if ((x>=250) && (x<=300)) // Delay Button
waitForIt(250, 1, 310, 50);
mode= mode ++ ;
myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect (250, 1, 310, 50);
// Select delay times
if (mode == 0) dTime = 0;
if (mode == 1) dTime = 1;
if (mode == 2) dTime = 2;
if (mode == 3) dTime = 5;
if (mode == 4) dTime = 10;
if (mode == 5) dTime = 20;
if (mode == 6) dTime = 30;
if (mode == 7) dTime = 50;
if (mode == 8) dTime = 100;
if (mode == 9) dTime = 200;
if (mode == 10) dTime = 500;
if (mode > 10) mode = 0;


if ((y>=70) && (y<=120)) // Trigger row
if ((x>=250) && (x<=300)) // Trigger Button
waitForIt(250, 55, 310, 105);
tmode= tmode ++;
myGLCD.setColor(255, 0, 0);
// Select Software trigger value
myGLCD.drawRoundRect (250, 55, 310, 105);
if (tmode == 1) Trigger = 0;
if (tmode == 2) Trigger = 10;
if (tmode == 3) Trigger = 20;
if (tmode == 4) Trigger = 30;
if (tmode == 5) Trigger = 50;
if (tmode > 5)tmode = 0;
if ((y>=130) && (y<=180)) // H position row
if ((x>=250) && (x<=300)) // H position Button
waitForIt(250, 110, 310, 160);
hpos= hpos ++;

myGLCD.setColor(255, 0, 0);
myGLCD.drawRoundRect (250, 110, 310, 160);
if (hpos > 60)hpos = 50;
//----------wait for touch sub
void waitForIt(int x1, int y1, int x2, int y2)
while (myTouch.dataAvailable())
//----------draw grid sub
void DrawGrid(){

myGLCD.setColor( 0, 200, 0);
for( dgvh = 0; dgvh < 5; dgvh ++){
myGLCD.drawLine( dgvh * 50, 0, dgvh * 50, 240);
myGLCD.drawLine( 0, dgvh * 50, 245 ,dgvh * 50);
myGLCD.drawLine( 245, 0, 245, 240);
myGLCD.drawLine( 0, 239, 245, 239);
myGLCD.setColor(255, 255, 255);
myGLCD.drawRoundRect (250, 1, 310, 50);
myGLCD.drawRoundRect (250, 55, 310, 105);
myGLCD.drawRoundRect (250, 110, 310, 160);
myGLCD.drawRoundRect (250, 165, 310, 215);

// ------ Wait for input to be greater than trigger sub
void trigger(){

while (Input < Trigger){ Input = analogRead(A0)*5/100;

//---------------End Subrutines ----------------------

void setup() {
pinMode(0, INPUT);
// set up the ADC
ADCSRA &= ~PS_128; // remove bits set by Arduino library

// you can choose a prescaler from below.
// PS_16, PS_32, PS_64 or PS_128
ADCSRA |= PS_64; // set our own prescaler
void loop() {

while(1) {

// Collect the analog data into an array

StartSample = micros();
for( int xpos = 0;
xpos < 240; xpos ++) { Sample[ xpos] = analogRead(A0)*5/102;
EndSample = micros();

// Display the collected analog data from array
for( int xpos = 0; xpos < 239;
xpos ++)
// Erase previous display
myGLCD.setColor( 0, 0, 0);
myGLCD.drawLine (xpos + 1, 255-OldSample[ xpos + 1]* vsens-hpos, xpos + 2, 255-OldSample[ xpos + 2]* vsens-hpos);
if (xpos == 0) myGLCD.drawLine (xpos + 1, 1, xpos + 1, 239);
// Draw the new data
myGLCD.setColor (255, 255, 255);
myGLCD.drawLine (xpos, 255-Sample[ xpos]* vsens-hpos, xpos + 1, 255-Sample[ xpos + 1]* vsens-hpos);
// Determine sample voltage peak to peak
Max = Sample[ 100];
Min = Sample[ 100];
for( int xpos = 0;
xpos < 240; xpos ++)
OldSample[ xpos] = Sample[ xpos];
if (Sample[ xpos] > Max) Max = Sample[ xpos];
if (Sample[ xpos] < Min) Min = Sample[ xpos];
// display the sample time, delay time and trigger level
myGLCD.setBackColor( 0, 0, 255);
myGLCD.setFont( SmallFont);
myGLCD.setBackColor( 0, 0, 255);
myGLCD.print("Delay", 260, 5);
myGLCD.print(" ", 270, 20);
myGLCD.print(itoa ( dTime, buf, 10), 270, 20);
myGLCD.print("Trig.", 260, 60);
myGLCD.print(" ", 270, 75);
myGLCD.print(itoa( Trigger, buf, 10), 270, 75);
myGLCD.print("H Pos.", 260, 120);
myGLCD.print( itoa( hpos, buf, 10), 270, 135);
//myGLCD.setBackColor( 0, 0, 0);
SampleTime =( EndSample-StartSample)/1000;
myGLCD.print("Sec.", 205, 210);
myGLCD.print(" ", 280, 30);
myGLCD.print(itoa( SampleTime, buf, 10), 205, 220);
// Range of 0 to 64 * 78 = 4992 mV
SampleSize =( Max-Min)*78;
myGLCD.print("mVolt", 5, 210);
myGLCD.print( itoa( SampleSize, buf, 10),5, 220);
myGLCD.print(itoa( analogRead(A0)*4.15/10.23, buf, 10),110 ,220);


//-------------------------END PROGRAM

Step 7: Video of the Oscope in Action

Step 8: Another Video

<p>An excellent article!</p><p>I will be looking for a tft for my mega!</p><p>What sort of refresh rate do you think your tft has?</p><p>Have you considered reading the analogue port by interrupt-</p><p>I have a 153K oscilloscope design using a mega with hardware and software triggering.</p><p><a href="https://www.instructables.com/id/Arduino-High-speed-Oscilloscope-with-PC-interface/?ALLSTEPS" rel="nofollow">https://www.instructables.com/id/Arduino-High-speed...</a></p><p>It would be interesting to bring the two concepts together.</p>
<p>Sorry for the delay in responding. Thanks for your comment. I don't know the refresh rate of the screen, haven't checked the specs in detail. It would definitely improve the scope if you could increase the bandwidth by using your design. If you get the kit and try your concepts on it , please share.. If I have time I might try it myself..Again thanks.</p>
<p>The 3.2 inch screen and Shield finally arrived. I used my Mega rather than the Sainsmart.</p><p>Assembly was easy- I added connecters for the analogue port, pwm10, zero and 5V. Programming was not difficult- Henning, the library author has excellent documentation. I found no issues in implementing his protocols.</p><p>My scope runs at up to 237-238 Khz. </p><p>The sdcard reader which is on the shield, works and opens up the possibility of data saving. (Not to mention adding pictures)</p><p>This has produced a very nice stand alone oscilloscope.</p><p>Thanks for your work.</p>
<p>Can you give the code?</p>
<p>Hello,Which library you using for this?</p>
<p>How did you add images ?</p>
<p>Hi,</p><p>For this application I used <br>Henning's loadBitmap function- which is documented in the examples <br>supplied with his library. This requires that you convert a screen sized <br> (or less) picture to raw format. He supplies a program with his library <br> download for this. Or you can use his online converter at :</p><p><a href="http://www.henningkarlsen.com/electronics/t_imageconverter565.php" rel="nofollow">http://www.henningkarlsen.com/electronics/t_imagec...</a></p><p>I used a screen sized (320 x 240) file. <br></p><p>#include &lt;tinyFAT.h&gt;<br>#include &lt;UTFT.h&gt;<br>#include &lt;UTFT_tinyFAT.h&gt;<br>#include &lt;UTouch.h&gt;</p><p>// Initialize Screen and touch functions<br>UTFT myGLCD(ITDB32S,38,39,40,41);<br>UTFT_tinyFAT myFiles(&amp;myGLCD);<br>UTouch myTouch(6,5,4,3,2);<br>boolean logo = true;</p><p>word res;</p><p>const int chipSelect = 53; // sd select pin</p><p>void setup(){</p><p>pinMode(chipSelect, OUTPUT);</p><p>myGLCD.InitLCD();<br>myGLCD.clrScr();</p><p>int picsize_x = myGLCD.getDisplayXSize();<br>int picsize_y = myGLCD.getDisplayYSize();</p><p>if (logo){<br> if (file.initFAT()==0){<br> switch (picsize_x);<br> res = myFiles.loadBitmap(0, 0, picsize_x, picsize_y, &quot;LOGO.RAW&quot;);<br> if (res == 0){<br> delay(5000);<br> myGLCD.clrScr();<br> }</p><p>}</p><p>}</p><p>// more setup stuff</p><p>}</p><p>The use of the raw file for a one off display is fine.</p><p>However <br> having to convert multiple files seemed a little time consuming to me. <br>So I wrote an addition to the Henning's utft library to process 24 bit <br>bmp files directly. This works great and does not require UTFT_tinyFat <br>and tinyFat. The sdcard can be accessed using the standard arduino sd <br>library. My patch will load a screen sized bitmap in 1.79S, which is a <br>little faster than Henning's system.</p><p>I have also utilised the sd for data recording.</p><p>All in all John has detailed a very useful shield and lcd!</p>
<p>Hi,</p><p>I ordered the lcd a month ago- apparently it is somewhere between China and the uk.</p><p>In the mean time I have developed code which runs at <br></p><p>237.3 Khz, with configurable software triggering.</p><p><a href="http://forum.arduino.cc/index.php?PHPSESSID=3e1pvsuftle7jd7dpr055uicf4&topic=265298.0" rel="nofollow">http://forum.arduino.cc/index.php?PHPSESSID=3e1pvs...</a></p><p>I have also written software which runs at 1.2MHz using a TLV571, also with software triggering.</p>
<p>Great Instructable! It got me thinking and I decided to make my own PipBoy from it!</p>
Cool, thanks forsharing.. <br>
<p>neato! thanks, maybe ill see what uses i can for this</p>
<p>Cool grumpyboots.. thanks for sharimg!</p>
Finally found a nice project, you took some time putting my his on here thanks for taking the time..
<p>How would you modify the code to display a signal between 0.2 and -0.2 volts?</p>
<p>Hey, Why i cant updata in my mega2560 ,it away show Error compiling for board Arduino/Genuino Mega or Mega 2560.</p>
<p>how do i download the ino file</p>
can the arduino uno pull this off with same sketch?
<p>Nice job. But you didn't include those libraries. Actually you did, but the instructable editor cut them out as html tags. So kids, dont forget to include them.</p>
<p>Hello:</p><p>At this time I only have an 2.8 tft lcd with sd card socket that will work with my Uno. I would like to know before I start this project do you think this could be adjusted to work with what I have? </p><p>What I would like to do is collect the data and place on the sd card so I can analyzed at a later time. Editing the code for sd card is something I think I can do, but using an tft lcd is not. I would like to know your thoughts on this before I begin.</p><p>Thanks</p><p>~Chris</p>
<p>Your Libraries.zip file is corrupt!!</p><p>Could not extract your files, to bad great project. Thank You!!</p>
<p>Hi,can anyone help me to graph a analog input in 3.2''tft?any updated library available for this?</p>
<p>guys my library shows a problem in this line UTFT myGLCD (ITDB24E_16,38,39,40,41). with the following Message: UTF does not name a type. can someone help me?</p>
<p>What is the size of your tft?</p>
<p>Make sure you have the library properly instaled and that you run the demo programs, as described in steps. 4 and 5 before loading the oscpe sketch </p>
<p>if you are usimg the sainsmart kit the line should read::</p><p>UTFT myGLCD(ITDB32S,38,39,40,41);</p>
<p>Sir will you explain these lines.</p><p>Secondly, I am using 400x240 tft and the negative part of the waveform is disappeared and a horizontal line appears.</p><p>for( int xpos = 0; xpos &lt; 239;</p><p>xpos ++)<br>{<br>// Erase previous display<br>myGLCD.setColor( 0, 0, 0);<br>myGLCD.drawLine (xpos + 1, 255-OldSample[ xpos + 1]* vsens-hpos, xpos + 2, 255-OldSample[ xpos + 2]* vsens-hpos);<br>if (xpos == 0) myGLCD.drawLine (xpos + 1, 1, xpos + 1, 239);<br>// Draw the new data<br>myGLCD.setColor (255, 255, 255);<br>myGLCD.drawLine (xpos, 255-Sample[ xpos]* vsens-hpos, xpos + 1, 255-Sample[ xpos + 1]* vsens-hpos);<br>}</p>
<p>tell me if i can use </p>2.4 inch TFT touch LCD Screen Module and an arduino uno or not by using same libraries and code in this post ?
<p>I made it. Good tutorial-impressive work. Thank you. </p>
<p>Can this program work on aurdino UNO aswell ? how many pins does the lcd shied have ?</p>
<p>Looks more complicated the it is. The Lego enclosure is a nice touch!</p>
<p>what does ('UTFT' does not name a type) mean I get this when I told it to load the sketch.</p><p>Jim</p>
<p>UTFT myGLCD(ITDB32S,38,39,40,41);</p>
<p>Is to do this using a nano aruino v3.0?</p>
<p>I don't.think. so, sorry</p>
<p>Nice work! Only one thing, how did you solved the problem of the negative part of the signal when you plug in the function generator?</p>
<p>check tis instructabel to giv you an idea:</p><h2 class="title" style="margin-bottom: 7.0px;padding-right: 10.0px;padding-left: 10.0px;border: 0.0px;font-size: 20.0px;color: rgb(51,51,51);width: 275.0px;font-family: Helvetica Neue , Helvetica , Arial , sans-serif;background-color: rgb(255,255,255);">How to make an Arduino oscilloscope probe by <a href="https://m.instructables.com/member/NeoRecasata/" rel="nofollow" style="margin: 0.0px;padding: 0.0px;border: 0.0px;color: rgb(255,82,0);text-decoration: none;" title="view NeoRecasata's profile">NeoRecasata</a></h2><p>https://m.instructables.com/id/How-to-make-an-Arduino-oscilloscope-probe/</p>
<p>indeed it graph most part of the signal with the probe, but it keeps cutting a minimum part of the signal. </p>
<p>the signal needs to be &quot;conditioned &quot; to be between 0 and 5 volts before it is input into the arduino analog input. You may need to attenuate the signal and float it on a dc voltage. Use two resistors in series connect one end to ground and the other to the 5 volt arduino pin, connect a capacitor to the junction and to your function generator. Connect a jumper from the junction to the analog pin. This will float the waveform on a dc of 2.5 volts. You can use two 1 meg resistors and a .47 micro farad capacitor. Remember the voltage. From your function generator has to be 5 volts peak to peak,if it is not, you. Will need to attenuate it using a potentiometer..</p>
<p>thank you a lot man, it worked perfectly:)</p>
<p>glad to help...click the I made it button and share a picture if you want...</p>
Use a voltage divider and a capacitor at the input.
<p>Awesome project, I love it!!!</p>
<p>thanks...you've got some awesome projects too!</p>
<p>Thank you! :)</p>
<p>Nicely done ! Something every work bench should have.</p>
<p>Thanks Mr. E, By the way, I tried your<a rel="nofollow"> https://www.instructables.com/id/Donut-Protection-Device-Advanced-Arduino-Technique/ </a>, another awesome project, thanks for sharing </p>
<p>OK I see where the pins go, from the PDF it did not show this and now looking at your design on the Instructables Interweb site I must have been off in well thanks and sorry to have bothered you.</p><p>Jim</p>
<p>Johnag, Thought I was having trouble compiling because of different Arduino versions, but then realized where are the libraries after the include statement and also problems cutting and IDE code. It's up and running and can't to test something. Always wanted an oscilloscope, now I have one and will be following ur blog.</p><p>Great Job!!</p>

About This Instructable




More by johnag:Arduino Color LCD Message Clock  Arduino  DEMO series  Make an Oscilloscope Using the SainSmart Mega2560 with the TFT LCD shield and the 3.5 "color touch screen 
Add instructable to: