Arduino - Improved Poor Man's Oscilloscope

This Instructable continues the work presented here.  It provided a quick and easy way to turn your Arduino into an oscilloscope, though I found that usability was lacking.  I revamped the software this morning to allow for much better functionality and usability and have provided the new software here.  I haven't fully tested it out yet, so please post bugs in the comments.  Also, this is still a fairly limited scope, so don't expect too much in terms of performance.  To reiterate the other Instructable:

First, download Processing (free).
Second, download both the Arduino and Processing code I've provided here.
Third, upload the Arduino code and run the Processing code.

If you examine the Processing software, you will notice that a number of hot keys have been defined.  I won't repeat them here, but please take a look so you know the basic functionality.  These hot keys can quickly be edited to your liking.  Also, if you're having a hard time getting Processing to select the right com port there is a variable for that (note that this variable is the index in the list of available ports).

Lastly, I've added the ability to output a 2Hz square wave on the Arduino.  Connect this pin to your analog input to test the scope.  Enjoy!

10 People Made This Project!

Recommendations

  • First Time Author

    First Time Author
  • Big and Small Contest

    Big and Small Contest
  • Make it Glow Contest 2018

    Make it Glow Contest 2018

21 Discussions

0
None
Anirban pal

1 year ago

Does this oscilloscope display sine wave; triangular wave also??

0
None
MikeFromMA

1 year ago

This is a great tool for my occasional hobbyist use. I use the free Soundcard Oscilloscope from zeitnitz.eu for signals above 20 Hz. I want to monitor an opto-coupled signal from the relatively slow rotations of the disk on my Electric meter for my current project, an Arduino based house power meter, so this DC coupled Arduino scope is perfect.

0
None
ScholliY

2 years ago

I'm thinking about building a scope with this and a RPI + LCD.

Would I be able with some code modification to do multichannel?

0
None
AraY18

2 years ago

Great Project, also used the pull-down resistor to clean up the noise, works really well!

0
None
colzilla090

2 years ago

Nice project and thank you. Haven't been able to get my hands on a real scope...yet! so this is perfect for my BB projects.. thanks! i used your code and it works great! i'm on linux 64bit (ubuntu16)
the processin script i had to change Line 77 to

port = new Serial(this, "/dev/ttyACM0");

so it would detect my com.

i have a uno r3.

could you tell me the max frequency this thing can read please?

also, anything up to 5v is ok for A0 but anything above 5v needs a voltage divider and a buffer circuit? is that right?

0
None
DavidH520

2 years ago

Little update to get it to work well what i had to do on windows 10 and process 3.0.2
Had to change the word [com_port] to [0]
If you try and run the program and it freezes it will show an error the line with this command

1 reply
0
None
difranc3

2 years ago

Awesome project....this will help greatly. Do you think its possible to have it output to a ascii file?

0
None
TheGoodLife

3 years ago

Is it possible to modify this for -ve and +ve voltages?

1 reply
0
None
rbalani

2 years ago

Great job!

The scope is working perfect here. I've been testing some other arduino/processing scopes but yours seems to be the one!

Tks.

0
None
LukaM5

2 years ago

Help! I also have the problem on line 77, but how do i specify the port on Linux? I tried putting in /dev/ttyUSB0 a bunch of different ways, but nothing works. Anybody made it?

1 reply
0
None
LukaM5LukaM5

Reply 2 years ago

Ok, I made it work.It was looking for the Arduino on /dev/ttyS1, but it was on /dev/ttyUSB0 so I just made a symlink!

#sudo su

#rm /dev/ttyS1

#ln -n /dev/ttyUSB0 /dev/ttyS1

0
None
DoğanK1

3 years ago on Introduction

also, it'll maybe better if there is dual channel option

0
None
bersham

3 years ago on Introduction

when i try to run the processing code i get and error

ArrayIndexOutOfBoundsException: 0

1 reply
0
None
bershambersham

Reply 3 years ago on Introduction

i think 0 indicates the port number , i changed it to 5 ( the one iam using for the arduino) yet the error is the same (with 5 instead of 0)

0
None
scottgriz

3 years ago on Introduction

What a great project. I was looking for a simple oscope to test a circuit for another arduino project. I am just learning and I found that playing around with this project helped me to learn a lot. With the help of my brother who is an electrical engineer, we were able to make some efficiency changes to the code.

The first idea was to attempt to send the sync byte only once in order to increase the overall efficiency. That only worked partially. Due to an oddity in the way the serial port starts up, we were only able to achieve sync about 20% of the time. We would have to start processing first and then repeatedly reset the Arduino. So my brother got an idea. The implementation is quite a ways over my head but I will attempt to explain the basics and post the code changes.

In the original code, the arduino sends a sync byte, and two data bytes to encompass the 10bit analog stream. This amounts to three bytes sent for every 10 bits of needed data which could be encompassed inside two bytes. So what my brother did was use the upper few bits of the upper byte to place a sync flag and then read that back in each cycle of data transmission. So instead of using a full byte to achieve a data sync, only two are used. The improvement is about 30%. I was able to see signals of around 6Hz clearly on the oscope.

I hope this works. I'll be interested in hearing what others get for results.

-Scott

So here is the code for the Arduino side and then Processing below that.

Arduino Code - Replace the loop() with this...

==========

void loop() {

int loval;

int hival;

int val = analogRead(ANALOG_IN);

hival = ( (val >> 8) | ( val & 0x80) >> 3) | 0x80;

loval = (val & 0x7f);

Serial.write( hival & 0xff );

Serial.write( loval & 0xff );

}

Processing Code - Replace all of getValue() with this...

=============

// Read value from serial stream

int getValue() {

int value = -1;

int loval;

int hival;

while (port.available () >= 2)

{

hival = port.read();

if((hival & 0x80) == 0x80) { // found hival flag, now read loval

loval = port.read();

if((loval & 0x80) == 0) { // loval flag = 0, as expected

value = ((hival & 0x03) << 8) | ((hival & 0x10) << 3) | loval;

}

else

{

// error - low byte flag <> 0 as expected

value = -1;

}

}

else

{

// error - high byte flag missing

value = -1;

}

}

return value;

}

0
None
sysop

3 years ago on Introduction

very nice...

This bit of processing code might help some one else determine the index of their serial port;
------

import processing.serial.*;
// List all the available serial ports and its index:
for (int i = 0; i < Serial.list().length; i++) {
println(i,Serial.list()[i]);
}


------