Instructables

Arduino - Multi-Channel Oscilloscope (Poor Man's Oscilloscope)

I am presenting software upgrades for the Arduino Oscilloscope (Poor Man's Oscilloscope) that allow to visualize two or three data channels simultaneously. The main features are identical to the original oscilloscope with exception of a few lines that I added to improve the users ability to estimate what the actual measured voltages are. RuiSantos had found the original software in the net and shared this information in his instructable and on his website. Thank you very much RuiSantos for sharing this.
Note that this "device" is not an actual oscilloscope. Most of the features you'd expect from an oscilloscope are not available. However, if you like to visualize data that is not too fast, then this is simply awesome. For example I will be using it to check a data sequence that I am going to create with a couple of 555 timers. But that is another story.

Features of the software/oscilloscope:
1-channel (original and fastest), 2-channel (slower), or 3-channel (even slower) data acquisition and display
0-5V signal range determined by hardware, i.e. Arduino
Time scale zoom in/out by pressing +/-
Red line = channel1 data
Green line = channel2 data
Blue line = channel3 data
Grey lines = 0.5V steps
Dark yellow lines = 1V steps
Screenshot functionality: On mouse button click the program stores a screen shot of your data window. This essentially allows you to "stop" the data and look at it. Convenient for data analysis. To make this work you have to go into the program "draw ()" section and adjust the file path to one that works with your computer.

All you need is an Arduino and a USB cable.
 
Remove these adsRemove these ads by Signing Up
txoof3 months ago

Thanks for the great instructable. I'm having some trouble with your Processing sketch though. I get the following error:

The function readStringUntil(short) does not exist.

I'm running processing v2.1 on OS X. I've managed to run other processing oscilloscope sketches using single outputs, but was intrigued by your multiple output version. Can you offer any suggestions?

Also, where can I set the serial port (2) in the sketch? I can't quite work that out.

Thanks for the help!

txoof txoof3 months ago

Wow! I just got everything working and this is fantastic. In the hour I've been playing with your sketches I've learned so much about how 555s work! Actually getting to see on a 'scope what's happening to the voltages is really instructive. Thanks very much for this post!

In other news: The problem I had is due to the fact that the function has been removed in the latest version. More details here: http://forum.processing.org/two/discussion/838/fun...

An older version of processing works great.

Superbender (author)  txoof2 months ago

Hi txoof,

Sorry about my delayed answer. I am really glad to hear that you enjoy working with the scope. I learned a lot when programming the extra channel versions and it makes my day to hear it that it is being used. Good input on the processing version / issue as well. I haven't done anything with processing with the exception of this scope. So good to know when I start the scope up again on my freshly installed computer.

Ubiqvit4 months ago
Hello everybody! I have arduino Mega ADK and decided to try out this project. Anyway, i tested it with function generator and I can nicely see slow (<10Hz) frequency signals. But when frequency is increase above 15 Hz signal becomes unreadable. It looks like some random(aliasing) signal. In the comments I read that you can read signals up to kHz. Any advice what could be wrong? Thank you for answer.
Superbender (author)  Ubiqvit4 months ago
Hi Ubigvit,
I never really hooked it up with a function generator. I typically look at pretty slow TTL type signals only with this. I'll put this on my list to do and will check it out in the next couple of weeks (or more realistic: sometime this year :) ). In any case, I would have guessed the speed to be in the range you are observing.
If you think about it, 10 -15 Hz doesn't really sound that bad considering that the data is being send via serial connection, which takes a significant amount of time. The speed will further depend on how many channels you actually were looking at. The one channel version should be faster than the two channel version, should be faster than the three channel version.
I found another option to increase the speed for my old computer is to reduce the window size. This will also increase the response time. To do that find line:
size(1280, 480); and change it to a smaller size.
Last not least if you like to look at kHz signals you might be better off trying some other oscilloscopes builds. There are a number out there that are working with the input into an audio card, if I remember correctly. For starters, check this list: http://www.instructables.com/id/DIY-Oscilloscopes/
I'll send an update when I get to check my system with a function generator.
WWC11 months ago
Hi
I am having trouble with your scope. I can get readings in the Arduino serial monitor but can not get any output on the Processing scope. I tried changing the port number to the port i am using but then it throws an error. I think i am not setting something correctly in the processing code, any hints.

Thanks
Wayne
Superbender (author)  WWC11 months ago
WWC,
Hard to come up with something without seeing the code.
If you can see the values on the serial monitor it seems to me that it has something to do with the processing script.
1. Did you check if a simple script runs in processing?
2. Did you get the single channel version of the scope to work for you? You had a post there that you had some difficulties with it. I'd suggest to confirm the single channel version is working and then we can work our way up to multi-channel.

Post or send me your code and I'll look at it.
WWC Superbender11 months ago
Hi thanks for the reply.
Yes running in Processing. The scope screen will display but no wave forms will display.
Yes the single channel version i can't get to show in Processing also, although it does show in the serial monitor.
This is of-course the single channel mode sketch that i was trying.
Thanks

#define ANALOG_IN 0

void setup() {
Serial.begin(9600);
//Serial.begin(115200);
}

void loop() {
int val = analogRead(ANALOG_IN);
Serial.write( 0xff );
Serial.write( (val >> 8) & 0xff );
Serial.write( val & 0xff );
}


/*
* Oscilloscope
* Gives a visual rendering of analog pin 0 in realtime.
*
* This project is part of Accrochages
* See http://accrochages.drone.ws
*
* (c) 2008 Sofian Audry (info@sofianaudry.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
import processing.serial.*;

Serial port; // Create object from Serial class
int val; // Data received from the serial port
int[] values;
float zoom;

void setup()
{
size(1280, 480);
// Open the port that the board is connected to and use the same speed (9600 bps)
port = new Serial(this, Serial.list()[0], 9600);
values = new int[width];
zoom = 1.0f;
smooth();
}

int getY(int val) {
return (int)(height - val / 1023.0f * (height - 1));
}

int getValue() {
int value = -1;
while (port.available() >= 3) {
if (port.read() == 0xff) {
value = (port.read() << 8) | (port.read());
}
}
return value;
}

void pushValue(int value) {
for (int i=0; i values[i] = values[i+1];
values[width-1] = value;
}

void drawLines() {
stroke(255);

int displayWidth = (int) (width / zoom);

int k = values.length - displayWidth;

int x0 = 0;
int y0 = getY(values[k]);
for (int i=1; i k++;
int x1 = (int) (i * (width-1) / (displayWidth-1));
int y1 = getY(values[k]);
line(x0, y0, x1, y1);
x0 = x1;
y0 = y1;
}
}

void drawGrid() {
stroke(255, 0, 0);
line(0, height/2, width, height/2);
}

void keyReleased() {
switch (key) {
case '+':
zoom *= 2.0f;
println(zoom);
if ( (int) (width / zoom) <= 1 )
zoom /= 2.0f;
break;
case '-':
zoom /= 2.0f;
if (zoom < 1.0f)
zoom *= 2.0f;
break;
}
}

void draw()
{
background(0);
drawGrid();
val = getValue();
if (val != -1) {
pushValue(val);
}
drawLines();
}
Superbender (author)  WWC11 months ago
Hi WWC,
I tried a couple of things and got your code running on my machine. Here is my report. Hope that fixes it.

First I tried to run my one channel oszi scripts to confirm my setup works. => success.
Second I tried your arduino code with my processing code. => success
Third I tried your arduino code with your processing code. Three issues came up:
1)
The window was too large for my screen, so I made the window smaller. This should also increase the response time. To do that find line:
size(1280, 480);

change into:
size(640, 240); a couple of errors came up that I corrected as follows:

2) Seemed like a loop wasn't working. To correct it find this section:
void pushValue(int value) {
for (int i=0; i values[i] = values[i+1];
values[width-1] = value;
}

change into:
void pushValue(int value) {
for (int i=0; ivalues[i] = values[i+1];
values[width-1] = value;
}

3) Seemed like another loop wasn't working. To correct it find this section:
find this section:
int x0 = 0;
int y0 = getY(values[k]);
for (int i=1; i k++;
int x1 = (int) (i * (width-1) / (displayWidth-1));
int y1 = getY(values[k]);
line(x0, y0, x1, y1);
x0 = x1;
y0 = y1;

change into:
int x0 = 0;
int y0 = getY(values[k]);
for (int i=1; ik++;
int x1 = (int) (i * (width-1) / (displayWidth-1));
int y1 = getY(values[k]);
strokeWeight(2); /* Draw thicker lines */
stroke(255, 0, 0); /* Draw a red line for channel1 */
line(x0, y0, x1, y1);
x0 = x1;
y0 = y1;

After that it worked as it should. Looks to me that you may have been plotting either none or only one data point.
Check out the changes and let me know.
Superbender (author)  Superbender11 months ago
/*
Correction to the last reply. Seems like there was a copy / paste issue when I pasted the code. Don't know if that was a user error, my computer, or the website. In any case you'll notice that the codes under 2) and the codes under 3) are the same for the change to section. There are parts missing.
Let me try to write it out without using copy / paste;
New 2)
Find:
void pushValue(int value) {
for (int i=0; i values[i] = values[i+1];
values[width-1] = value;
}

Change into:
void pushValue(int value) {
for (int i=0; ivalues[i] = values[i+1];
values[width-1] = value;
}

New 3)
Find:
int x0 = 0;
int y0 = getY(values[k]);
for (int i=1; i k++;
int x1 = (int) (i * (width-1) / (displayWidth-1));
int y1 = getY(values[k]);
line(x0, y0, x1, y1);
x0 = x1;
y0 = y1;

change into:
int x0 = 0;
int y0 = getY(values[k]);
for (int i=1; ik++;
int x1 = (int) (i * (width-1) / (displayWidth-1));
int y1 = getY(values[k]);
strokeWeight(2); /* Draw thicker lines */
stroke(255, 0, 0); /* Draw a red line for channel1 */
line(x0, y0, x1, y1);
x0 = x1;

So I hope this time I did it right.
*/
y0 = y1;
Superbender (author)  Superbender11 months ago
Again the code was changed when I pressed the "post" button.
Very strange. I'll pm you and send you the code in a txt file.
WWC Superbender11 months ago
Copy and past in this form rarely works as you have found out.
CraigHyatt11 months ago
Install the Windows 32 bit version of Processing 2.0.  The Windows 64 bit version says "serial does not work in 64 bit mode" when you run it.
CraigHyatt11 months ago
/* CommaDelimitedOutput sketch */
const int CHANS=3;
void setup() {
  Serial.begin(115200);
  // Increase ADC timebase to 1MHz
  bitClear(ADCSRA,ADPS0);
  bitClear(ADCSRA,ADPS1);
  bitSet(ADCSRA,ADPS2);
}

// Sends CSV from ports A0, A1, ... up to CHANS channels
// Readings 0..1023 -> 0..ADCREF (typically 5V or 3.3V)
void loop() {
  Serial.print("H,");
  for (int i=0; i<CHANS; i++) {
    Serial.print(analogRead(A0+i));
    Serial.print(",");
  }
  Serial.println();
  delay(50);
}
i used a.01 capacitor for the variable capacitor
I made a probe for it http://www.instructables.com/id/How-to-make-an-Arduino-oscilloscope-probe/
Superbender (author)  NeoRecasata1 year ago
Sweet. A probe is a definitely a good addition to the scope. I'll check out your instructable as soon as I find some time. Thanks for letting me know.
Pro

Get More Out of Instructables

Already have an Account?

close

PDF Downloads
As a Pro member, you will gain access to download any Instructable in the PDF format. You also have the ability to customize your PDF download.

Upgrade to Pro today!