Introduction: 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!
13 People Made This Project!
- lucasnobrega98 made it!
- illpallozzo made it!
- bgrupczy made it!
- usevimli made it!
- Kepp27 made it!
- LukaM5 made it!
- clovisf made it!
- Kevin Mitchell made it!
- Borowik made it!
See 4 More
21 Comments
6 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?
Reply 4 years ago
Since this is software based, the more channels you have, the less bandwidth can be measured.
5 years ago
Does this oscilloscope display sine wave; triangular wave also??
Reply 4 years ago
Yes. It reads analog values so any signal you give it.
5 years 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.
6 years ago
Great Project, also used the pull-down resistor to clean up the noise, works really well!
6 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?
6 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
Reply 6 years ago
On line 77
6 years ago
Awesome project....this will help greatly. Do you think its possible to have it output to a ascii file?
6 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.
7 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?
Reply 7 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
7 years ago on Introduction
also, it'll maybe better if there is dual channel option
7 years ago on Introduction
This is very useful thank you.
7 years ago on Introduction
when i try to run the processing code i get and error
ArrayIndexOutOfBoundsException: 0
Reply 7 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)
8 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;
}
8 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]);
}
------
8 years ago on Introduction
Hey JP..!!!
Really cool and usefull, many Thanx..!!