Arduino – Poor Man’s Oscilloscope

Today I’ll talk about a really good project you can do with your Arduino! This is the best way you can have a cheap oscilloscope around, I didn’t write this code, I’ve found it on the internet a while back ago and I’ve decided to share this awesome project. Let’s start…

First, download Processing. It’s free Click here to download. You don’t need to install anything, It runs like the Arduino IDE.

Upload this code to your Arduino

/* 
  Complete project details: https://randomnerdtutorials.com/arduino-poor-mans-oscilloscope/
*/

#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 );
}

View raw code

Then Run this code in Processing IDE

/*
 * 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 ([email protected])
 *
 * 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 <http://www.gnu.org/licenses/>.
 */ 
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<width-1; 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<displayWidth; 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();
}

View raw code

And then you just need to connect the Arduino analog pin 0 to the signal you want to read.

And It’s done!

Parts required

Schematics

This is the circuit I’ll be measuring , it’s a simple 555 timer circuit… that flashes an LED.

555 timer

Watch the video demonstration

Thanks for reading, you can contact me by leaving a comment. If you like this post probably you might like my next ones, so please support me by subscribing my blog and my Facebook Page.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

18 thoughts on “Arduino – Poor Man’s Oscilloscope”

  1. Hi Rui,
    Just got today the Teensey and used your intro toturial.
    I would like to see how many sample points I can get via the Teensey Serial port (from Analog Pin 0). I sued your Code but the second one that should draw the trace caused several errors.
    especially on the line “import processing.serial.*;”

    Are there any preconditions?
    btw: I am quite new to the Arduino stuff and C-Programming, I just modify some example codes.

    Thanks

    Reply
  2. Very informative post, i’m regular reader of your blog.
    I noticed that your site is outranked by many other blogs in google’s search results.
    You deserve to be in top10. I know what can help you,
    search in google for:
    Omond’s tips outsource the work

    Reply
  3. In every port, you will be amused by the different
    activities such as partying in the different dockside establishments.
    You will spend less time building your boat if the
    plans are clear and easy to follow, you will spend less money trying to fix
    problems due to inadequate or poorly designed plan elements.
    But what good is sailing without food that appeals to the palate.

    Reply
  4. Hi Rui,

    Can you explain what the code is doing?
    Can the o’scope traces be displayed in the serial plotter? How would you do that?

    Thanks!

    Reply
      • OK – room for the serial plotter to improve, I guess.

        You still didn’t answer my first question 🙂

        What is this code doing:
        int val = analogRead(ANALOG_IN);
        Serial.write( 0xff );
        Serial.write( (val >> 8) & 0xff );
        Serial.write( val & 0xff );

        Thanks!

        Reply
        • I know this was asked a long time ago, but in case someone is reading this and wondering, the code reads read the value (voltage) from pin ANALOG_IN (defined earlier as pin 0) into variable “val” of type integer (which is 16-bit). This value is from 0 to 1023 (corresponding to the range of 0 V to VCC V – 5V or 3.3V depending on which Arduino board is it). It then sends this value to the serial port (-> USB port of the computer), with a “magic” prefix of 0xFF. (val >> 8) & 0xff is the upper 8 bits of the 16-bit int, and val & 0xff is the lower 8 bits – >> and & are just binary operations (right shift and binary AND).

          Reply
          • sorry but 16 bit is around 65k resolution. So 1024 is 10 bit resolution and 8 bit is only 256 but dont understant why the corect way is not “Serial.write( val & 0x00 );”?? i get that left shift 8 positions and then write “val” witch is 10 positions but after that 0xff is 256 or 8 bit .. and last 2 bits are they not somehow colide with your 10 bit val… i know i missing something 🙂

          • An int in this context is 16 bit (two bytes). Arduino’s ADC is 10-bit, indeed. So, any result of analogRead will obviously have the upper 6 bits as zeros. The code above wants to write the data to serial output. Serial.write can write bytes, strings or arrays (must specify the length). The author of the above code decide to write it as bytes. A 16-bit int consists of two bytes (in our case the upper byte has only 2 relevant digits, the rest are zeros, but it doesn’t really matter). To extract the upper and lower bytes from an int, we can use respectively (val >> 8) & 0xff and val & 0xff. This is basic binary arithmetic. Just write 16 random binary digits on a piece of paper and do these operations by hand: “shift right by 8 positions, with the overflowing digits just disappearing, then bitwise AND 111111111”, or just “bitwise AND 11111111” and you will see how it works.
            You mentioned val & 0x00 (might as well have written val & 0), this doesn’t make sense, this will be always zero (anything & 0 is 0). If something’s still not clear, just read up on bitwise binary arithmetic operators

  5. What is the maximum frequency it could currently display, and what could be modified to support higher frequency signals.
    Is there a possibility that they update the project and make it for an ESP32 or maybe a Raspberry Pico?

    Reply

Leave a Reply to Rui Santos Cancel reply

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.