Introduction: Arduino Oscilloscope

A very basic and easy to make arduino PC oscilloscope.

Features:

  • 50K samples/second
    (actually it can go up to 110K but the signal will become noisy)
  • Auto trigger
  • Frequency counter
  • Reasonably accurate voltage readings (depending on the accuracy of the resistors used for the voltage dividers)
  • Optional: selectable voltage range: 5V, 6.6V, 10V, 20V

You'll need:

      • An Arduino Leonardo or Arduino Micro
      • 2 crocodile clamps
      • a 0.1µF capacitor (optional)
      • a 5.1V zener diode (optional)
      • a pc with Processing

      For the voltage dividers (optional, if you want to measure than 5V or want selectable range):

      • 2 two-pole dual throw switches
      • two 3K resistors
      • two 1.5K resistors
      • one 1K resistor
      • a small perfboard or breadboard


      If you only need to measure op to 5V, you can skip the voltage dividers and connect the probes directly to GND and A1. You'll have to modify the code a bit:

      In the arduino code, replace:

      ADMUX =  B00000000;         // select external reference and port 5 (A0)

      with:

      ADMUX =  B01000000;         // select internal reference (Vcc - 5V) and port 5 (A0)

      In the processing code, replace:

      // read switch position & set voltage range
       boolean switch1=((buffer[writeIndex*2]&(byte)8)==8);                                                 
       boolean switch2=((buffer[writeIndex*2]&(byte)4)==4);
       if (!switch1&&!switch2) voltageRange=20;
       if (!switch1&&switch2) voltageRange=10;
       if (switch1&&!switch2) voltageRange=6.64;
       if (switch1&&switch2) voltageRange=5;

      with:

      voltageRange=5;

      Step 1: Adding Voltage Dividers

      The circuit show above consists of:


      On the left: a 1:4 voltage divider between the probe and A1

      This will bring the voltage down to 1/4 of the input voltage. The analog pins can handle 5V, so this will allow for voltages up to 20V.

      Note that there are 2 input channels in the picture of the breadboard. Adding an extra channel slowed down the sampling rate dramatically (because continuous mode can't be enabled on the ADC), so I decided to leave it out in the final code.

      On the right: a switched voltage divider between 5V and the Analog Reference (AREF) pin
      You can use the switches to set the measuring range: 5V, 6.64V, 10V of 20V

      How this works:

      If configured to 'external reference', the ADC compares the voltage of the analog inputs with AREF, instead of 5V.
      Here's an example: suppose the probe is measuring 5V. The voltage on the A1 will be 5V/4 = 1.25V

      • If both switches are off, the voltage on the AREF pin is 5V.
        The ADC will read 1.25/5 = 25%
      • If switch 1 is off and switch 2 is on, the voltage on AREF is 2.5V
        The ADC will read 1.25/2.5 = 50%
      • If switch 1 is on and switch 2 is off, the voltage on AREF is 1.66V
        The ADC will read 1.25/1.66 = 75%
      • If both switches are on, the voltage on AREF is 1.25V
        The ADC will read 1.25/1.25 = 100%

      The second pole of each switch is connected to a digital input. We can read this pin to automatically adjust the voltage scale.

      A capacitor between the probe and ground
      Might not be necessary, but for some reason some pc's measure a lot of noise without it. The capacitor will solve that, but may slightly affect the signal when measuring high frequencies.

      A zener between A0 and ground
      To protect the arduino a little from overvoltage or reverse voltage (thanks, tttapa, for the tip!)

      Be careful:

      • If the analog reference is set to internal (default) while you are supplying voltage to the AREF pin, the arduino could get damaged. I did that, and it didn't damage mine, but better be safe and upload the proper code before connecting AREF.
      • the analog inputs can't handle negative voltages.
      • Don't exceed 5V on the arduino pins. It's probably a good idea to test the circuit with a voltage below 5V, so

        you don't damage the arduino in case the voltage divider on A1 was wired incorrectly.

      The arduino code was based on this excellent article:

      http://meettechniek.info/embedded/arduino-analog.html

      Good luck!
      Bram

      Step 2:

      Comments

      author
      sommarjobbarna17 (author)2017-07-12

      hello bram! first off, very nice project, I get some really good measurements even though i use the UNO and not the arduino specified in the instructable. but i do have one slight issue, i get some strange noise. between the noise the measures are accurate but pretty much unreadable. i read somewhere in the comments that this could happen if you used the UNO but i couldn't find a solution for it. do you have any suggestions on what i can do to cancel out the noise? i use the scopeP3 code and the 5v read only setup, so nothing extra but the arduino itself.

      thanks in advance

      author

      Hello,
      (Sorry for the late reply, It's been a while since I checked here.)
      It might have to do with power supply noise. Have you tried disconnecting your laptop and running it of the battery?

      Kind regards,
      Bram

      author

      Hello, please what do i do with the pde file (ScopeP3 and scopeP2). I cannot get the oscilloscope screen to show. I was using just the scope.ino code. please help!!!

      author
      BramMylemans (author)maryclair2017-09-21

      Hi,
      You should open it in Processing 2 (scopep2.pde) or Processing 3 (scopep3.pde). You can download processing for free at processing.org. Good luck.

      Best regards,
      Bram

      author
      MauroB28 (author)2017-06-04

      Could I use this project with Arduino Nano ?, which would have to move

      author
      MegaDAS (author)2016-12-23

      cool stuff

      author
      desmondtheredx (author)2016-11-18

      exactly 44 thousandth view 44000

      author
      GaneshG26 (author)2016-03-20

      Hello,

      I do not own a Micro or Leonardo, but I own an Uno. Will this instructable still work with the Uno?

      Thanks.

      author
      BramMylemans (author)GaneshG262016-03-20

      Hello Ganesh,
      It will work, but the sample rate would be limited by the serial speed.
      (You'll need about 800.000 bps for 50K samples/sec. I don't know how fast the uno's serial can go.)

      Regards,
      Bram

      author

      it can go upto 115200baud or bps

      author

      Someone on this thread claims his UNO goes up to 2Mbps.
      Perhaps the 115200baud is a limitation of arduino IDE's serial monitor?

      author

      see, the arduino CAN do 921600 baud, just the ide only goes to 115200

      cdd.PNG
      author

      >Perhaps the 115200baud is a limitation of arduino IDE's serial monitor?

      it indeed is. HyperTerminal can go upto 921600 baud. But anything above 115200 baud is lossy and subject to line interference so it is hardly ever used.

      hyperterm.png
      author
      nsoclo (author)BramMylemans2016-05-25

      Mr. Bram, how you can assumption 50k sps need 800.000 bps? can you explain to me? thx

      author
      BramMylemans (author)nsoclo2016-05-25

      Hello Nsoclo,

      50,000 samples/sec * 16 bits/sample = 800,000 bits per second.

      Regards,
      Bram

      author
      nsoclo (author)BramMylemans2016-05-31

      16 bits/sample ? in specification, Arduino ADC is 10 bit. why it can 16 bits/sample?

      tanks you very much Sir !

      author
      BramMylemans (author)nsoclo2016-05-31

      You're right, one sample is 10 bits, plus two bits for the switches, but it is sent as 2 bytes for simplicity (and because it doesn't matter on an arduino micro, where the ADC rate is the limiting factor).

      author
      nsoclo (author)BramMylemans2016-05-31

      thanks your information Sir, its helpfull.

      Regards,

      Narto

      author
      emallon (author)2016-08-30

      Nice work with the scaling/ranging. I've recently started noodling around with the serial plotter tool in place of processing, and it was relatively easy to emulate a triggered sweep function with a simple threshold triggered loop:

      https://edwardmallon.wordpress.com/2016/08/15/usin...

      author
      R Jordan Kreindler (author)2016-07-11

      An interesting topic. Nice job!

      author
      nevillekong1 (author)2016-03-22

      I like your oscilloscope! But I think it's better to show the result with a LCD ;)

      author
      PumidolL (author)2016-03-07

      Hi,

      I get an error on this line

      serial = new Serial(this, Serial.list()[keyCode-112], serialBaudRate);

      errpr: ArrayIndexOutOfboundsException:-122

      Im on OSX 10.11.1 thanks!

      author
      BramMylemans (author)PumidolL2016-03-07

      Hell Pumidoil,
      I can't test on Mac, but try pressing Fn together with the function key to select the serial port. Maybe Mac defaults to Fn lock.
      If that doesn't work, replace (in processing):

      serial = new Serial(this, Serial.list()[keyCode-112], serialBaudRate);

      with:

      serial = new Serial(this, COM3, serialBaudRate);
      //(replace COM3 with the right port)

      Let me know if it still doesn't work.

      author
      PumidolL (author)BramMylemans2016-03-07

      Hi,

      Thanks for fast reply! You just gave me the idea. It's the Fn button that freezes the program.

      I used onscreen keyboard to select COM port. Now it works flawlessly.

      author
      SamirTafesh made it! (author)2016-03-06

      Nice Instructables, i reproduce it and it is working as expected, good work and thank you, i learned a lot

      IMG_2333.JPG
      author
      brajomobil (author)2016-03-02

      Can you please explan how did you get 50k samples per sec?
      When I log raw data from serial port I can get max 12k samples per sec.
      Thank you In advance.

      author
      BramMylemans (author)brajomobil2016-03-02

      Hi Brajamobil,

      Are you using analogRead? If so, have a look at: http://meettechniek.info/embedded/arduino-analog.h..., and the atmega datasheet.

      The frequency can be increased by:
      - lowering the prescaler of the ADC, so it will run at a higher frequency.
      - setting the ADC to continuous mode, with an interrupt to read the data into an array.
      - sending multiple samples at a time (because each serial.write command has some overhead)

      author
      brajomobil (author)BramMylemans2016-03-02

      Hi Bram,

      I'm using your "scope.ino". In your code I don't see 50K samples going over
      serial port. I have installed serial logger to see If I am missing something.
      I am not questioning ADC sampling at 50K, just transferring that data over serial line. Serial baud is not enough.

      author
      BramMylemans (author)brajomobil2016-03-02

      Sorry, I misunderstood.
      What exactly does the serial logger count? 12K bytes/sec?
      Have you tried the processing sketch?

      author
      brajomobil (author)BramMylemans2016-03-03

      I tried your processing sketch. Refresh rate is not high because serial line is slow by design. You can't trasfer 50K samples over it. Search google for explanation of baud. After that please explain how did you manage to transfer that amount of data over it. If you can't then please correct your instructable.

      author
      BramMylemans (author)brajomobil2016-03-03

      Hey Brajamobil,

      Apparently the Micro and Leonardo don't use the UART for USB communications. They ignore the baudrate set in serial.begin(xxx), and allow for much faster speeds (up to 12Mbit/s).
      Thanks for pointing this out. I've updated the instructable.

      author
      Akshay Jha (author)2016-02-29

      Hii first of all thanks for this instructables . I am facing problems in measuring voltage more than 5volts it losts its accuracy below 5 volt it works fine but when I set switches on like 20v confriguation and it is also showing 20 volt on processing output but after this I applied 11v on probes it shows around 19 volts

      author
      BramMylemans (author)Akshay Jha2016-03-01

      Hi Akshay,

      If you have a voltmeter you could try measuring:
      - between A0 and GND: should be 1/4th of the voltage at the probe
      - between AREF and GND: depending on the switches, this should be 5V (20V scale), 2.5V (10V scale), 1.66V (6.66V scale) or 1.25V (5V scale)

      If all these are correct, perhaps pins D3 or D4 are connected to the wrong poles of the switches, selecting the wrong voltage scale. You can invert pins D3 and/or D4 in processing:
      boolean switch1=!((buffer[writeIndex*2]&(byte)8)==8);
      boolean switch2=!((buffer[writeIndex*2]&(byte)4)==4);

      Good luck! Let me know if it still doesn't work.

      author
      Akshay Jha (author)BramMylemans2016-03-01

      Thanks for the reply but unfortunately it doesn't work
      1. I've check voltage between A0 & Gnd it is giving exactly 1/4th of voltage
      2. I've also checked votage at Aref pin it also as you've mentioned
      3. At last I ve modify code according to you but it give me wrong values
      But it is working great below 10 volts but when I set switches to 20 volt mode it gives unwanted noise which was not present in any other confriguation

      author
      BramMylemans (author)Akshay Jha2016-03-01

      Hi Akshay,
      Strange. The only thing I can think of is that AREF is left floating when both switches are on. Have you tried connecting AREF directly to the arduino's 5V pin? (this should give you the 20V range)

      author
      Akshay Jha (author)2016-03-01

      You can see this unwanted noise but must tell you that lower than 10v it works very well

      1456855197079-1164252406.jpg
      author
      Dimitrisblamis (author)2016-02-10

      What is the maximun frequency it can measure?

      author

      In theory, half the sampling rate, about 25KHz. But you won't be able to distinguish the shape of the wafevorm anymore.

      author
      magkopian (author)BramMylemans2016-03-01

      With only two samples you can't represent any signal accurately unless it's a perfect square wave. In practice you need at least 10 samples of each period of the signal in order draw it accurately enough on the screen (by joining the dots), which means the maximum frequency is around 5Khz. Still pretty good for many low frequency applications though.

      author
      WannaDuino (author)2016-03-01

      Bram super man erg erg tof

      Kun je mij de Nederlandse uitleg mailen aub, ook ik wil je graag na doen in het maken, van 0v tot 20v of meer zelfs als dat kan 35/40v Mischien

      author
      WannaDuino (author)WannaDuino2016-03-01

      Sorry mijn email is. wannaduino@gmail.com

      image.jpg
      author
      rbalani (author)2016-02-13

      Hi there, nice Instructable! I hope you can help me to reproduce it.

      I just copied your code but I get an error in Processing: I get a message saying "Null Pointer Exception" and line 15 ["PFont font= createFont("Lucida Console", 12, false);]. It's not clear if the rest of the code is OK or if it has stopped verifying in the first error.

      Any idea how I can correct this? It's my first time using Processing (v3.0.1).

      Tks.

      author
      BramMylemans (author)rbalani2016-02-13

      Hi Rbalani,

      It could be the font that is missing. Try:

      PFont font= createFont("Arial", 12, false);

      Also, in Processing 3:

      frame.setResizable(true);

      should become:

      surface.setResizable(true);

      Good luck!

      author

      still error sir, what can i do?

      Untitled.png
      author

      Sorry, I hadn't tested it in P3.
      Now I have, and I've just added and updated scopeP3.pde to the instructable. Please let me know if it still doesn't work.

      author

      it's work, thank you very much.

      author
      EbudS (author)2016-02-09

      Is this low cost? How much would it take for me to make this?

      author
      mir007 (author)EbudS2016-02-09

      Hi, dependent where you buy your stuff it will cost about $5-10.

      author
      EbudS (author)mir0072016-02-09

      Then is there any way I can make a lowcost oscillator that can display analog and digital signals?

      author
      mir007 (author)EbudS2016-02-09

      An oscillator generates a signal. With a scope you can make the signals visuable.For this project is not stand alone. You need a PC to make the scope signals visuable.

      For the Arduino there are a lot of projects to make these, generators and scopes. For a generator example see "https://www.instructables.com/id/Arduino-Waveform-Generator/".

      About This Instructable

      57,961views

      802favorites

      License:

      More by BramMylemans:Arduino oscilloscope
      Add instructable to: