Picture of Girino - Fast Arduino Oscilloscope
I am a Physicist and the nicest part of working in this field is that I get to build my own instruments. With this way of thinking, I decided to build a homebrew Arduino Oscilloscope. This instructable was written with the purpose of teaching a bit about microcontrollers and data acquisition. This is an extreme project because I wanted to squeeze out from Arduino as much velocity as I could, I have not seen any other Arduino Oscilloscope as fast as this one.

Some time ago I was working on an Arduino project and I needed to see if the output signal was into compliance with the specifics. Thus I spent some time on the internet looking for Arduino Oscilloscopes already implemented, but I did not like what I found. The projects that I found were mostly composed of a Graphical User Interface for the computer written in Processing and a very simple arduino sketch. The sketches were something like:
void setup() {

void loop() {
    int val = analogRead(ANALOG_IN);
This approach is not wrong and I do not want to insult anyone, but this is too slow for me. The serial port is slow and sending every result of an analogRead() through it is a bottleneck.

I have been studying Waveform Digitizers for some time and I know reasonably well how do they work, so I got inspiration from them. These were the starting points of the oscilloscope that I wanted to create:
  • the incoming signal should be decoupled from the arduino to preserve it;
  • with an offset of the signal it is possible to see negative signals;
  • the data should be buffered;
  • a hardware trigger is required to catch the signals;
  • a circular buffer can give the signal shape prior to the trigger (more to follow on this point);
  • using lower lever functions that the standard ones makes the program run faster.

The sketch for the Arduino is attached to this step, along with the schematic of the circuit that I made.

The name that I came up with, Girino, is a frivolous pun in Italian. Giro means rotation and adding the suffix -ino you get a small rotation, but Girino also means tadpole. This way I got a name and a mascot.
Remove these adsRemove these ads by Signing Up
1-40 of 55Next »
GaryD24 days ago

Great work thanks Chatanga and Caffeinomane. One glitch: the codes for the reference voltage are not correctly aligned between Girino and the GUI. I updated setVoltageReference(... in settings.cpp as follows:

switch (reference)


case 0:




//case 2: correct mismatch with GUI

case 3:





Right! I missed this one. The value used by the Girino is a bit misleading, but I’ve released a new version whose code match the one used by Girino. This new version also introduces some UI refinements with more readable unit increments and the ability to change parameters while waiting for a trigger.

subatomicsushi made it!4 days ago

I built a two-channel standalone version. It features a +/- 12 V input range, adjustable gain, AC or DC coupling, automatic or manual trigger threshold, and the USB port is exposed for serial connection. Excellent project sir!

Chatanga21 days ago

Hi all,

project is starting to getting old, but, for those still interested in,
I've developed a(nother) small Java GUI frontend to drive the Girino:

It is not in pure Java since there is a native part to deal with the
serial communication, but it is the same as the one used by Arduino.
This way and provided you have a working Arduino IDE on your machine,
you should have no problem to run it on you Linux / Mac / Windows. Take
some time to look at the README file however since there is a lingering
problem with the 'wait duration' settings.

I’ve released a new version which mostly fixes launching problems on Mac and Windows:

I’ve also tried the optimization described by womai and it has finally allowed me to unlock the x8 and x16 prescalers. Nice! The x4 prescaler is still out of reach, but I don’t think the code could be optimized further.

Sine signal acquired on Mac.png
hitchcme made it!4 months ago

I Made it, modified it, couple transformers inside an Iomega hard drive enclosure, home etched shield, working with a mega 2650, and..... here's a labview student edition interface, and an XCode Cocoa OpenGL interface =>still in progress. it could be called the Cocoa-O-O-G-G-L-Scope or I don't know. ta da!!!!


Hi there! I'm trying to use your Labview program to interpret Girino data, which I already configured properly. My problem is that when running the program I dont see anything in the graph, although it recognize the arduino into the corresponding port. I need to change something in the code of the Arduino code or in Labview? Thank you very much for everything, especially for sharing your work, greetings! (PD English its not my native language, sorry if you have trouble understanding me)

hitchcme hitchcme4 months ago

If one was working with a Windows machine, it is possible to just copy side by side everything, recreating everything as if you had done it yourself, which... I am happy to share!

hitchcme hitchcme4 months ago

I meant a windows machine with LabView.

womai2 years ago
Two ideas to make the code more efficient (run faster):

The calculation

ADCCounter = ( ADCCounter + 1 ) % ADCBUFFERSIZE;

involves an integer division which tends to be time consuming (at least on a Microchip PIC - I do not know Atmel as well). Instead, try

if (++ADCCounter >= ADCBUFFERSIZE) ADCCounter = 0;

Second, you can completely avoid the time required to evaluate


and live without the wait variable if you simply set stopIndex to a value that the counter never reaches, as long as you aren't yet in the post-trigger phase. I.e. during initialization (when starting a new sweep) set

stopIndex = ADCBUFFERSIZE + 1;

and when the trigger event happens then just do as you did so far, but without the boolean wait variable:

// Disable Analog Comparator interrupt
cbi( ACSR,ACIE );

// Turn on errorPin
//digitalWrite( errorPin, HIGH );
sbi( PORTB, PORTB5 );

stopIndex = ( ADCCounter + waitDuration ) % ADCBUFFERSIZE;

and the ADC ISR routine becomes

if (++ADCCounter >= ADCBUFFERSIZE) ADCCounter = 0;

if ( stopIndex == ADCCounter )
cbi( ADCSRA, ADEN );
freeze = true;
Jimmus womai12 days ago

I wish I had read this before I did my project. I could only get it to work with a prescaler as low as 4. I wanted to do 2, but it wouldn't respond.

After I had already torn out my test setup and put my project into production, I thought that maybe the ISR was taking too long. I looked at the assembly it created, and I came to the same conclusion that you did, that the integer division was part of the culprit. My solution would have been to set ADCBUFFERSIZE to 1024, which the compiler converted to a simple AND instruction. But I like your solution better. Isn't it funny how we sometimes write code that looks more elegant in C, but using a simple if block (that takes more code in C) actually builds more efficient machine code?

Caffeinomane (author)  womai2 years ago
Thank you very much womai for your precious advices!
This period is very though for me but I am planning to modify the project according to your suggestions.
Jimmus made it!12 days ago

Thank you so much for this. I had tried multiple ways to beg or borrow a recording oscilloscope to debug one of my projects, and it just wasn't working out. Finally I broke down and built this. I was worried that I didn't have the right probe hardware, or that it wouldn't be fast enough, or that it would brick my Arduino somehow. My fears were unfounded--it worked perfectly. I had to modify it slightly to fit my project, but when all was said and done, it told me exactly what I needed.

Data6.svg is the plot (raw data sucked out of the Arduino using the supplied python script, modified, and imported into a spreadsheet and plotted from there) of the original waveform. Prescaler = 4. The project was resetting or hanging my microcontroller when I turned off the relay. The probe is between the output pin on my microcontroller and the ground. Notice the waveform bottoms out at -0.5 volts, which I expect kicks in the protection diodes, and does screwy things to the microcontroller.

I tried several different remedies. Several different capacitors, and two different diodes, and the Girino showed me exactly how each modification affected the waveform. I picked the two components that made it work the best, and used them. Instead of guessing, I could be confident that these were the proper components, with the proper values, and would actually fix the problem.

Data8.svg is the plot with a Schottky diode across the relay coil, and a 1 uF capacitor between the output pin and the ground. The wave still goes negative, but only to about -0.2 volts, and my microcontroller can handle that. My project is now working like a champ!

Again, thank you for your work on this, and for sharing it with the world so that people like me can benefit from it.

acboother18 days ago

Have a look at and see if this is of any use for your PC display. There is a lot of work in buffering the input and multitasking the display code (very different to your Python approach or one using Processing). However this version does not read binary data...

Hello! My professor and I are doing research that requires us to make an inexpensive Multi-channel analyzer. A component of the MCA is the Arduino Uno, which we want to turn into an ADC. The Uno, however, is too slow so we turned to the instructable here for the Sketch that's supposed to increase the frequency at which the Uno reads analog signals. However, when we try to run the code (with minor changes) the serial monitor outputs data that makes no sense. We used Girino.7z. Here are the changes we made;

* When we download the Girino code and turn on debugging (by setting DEBUG=1 in Girino.h), we get the expected output:


# setup()

Girino ready

# ADCCounter: 0

# stopIndex: 65535

# wait: 0

# freeze: 0



# ADCCounter: 0

# stopIndex: 65535

# wait: 0

# freeze: 0



// repeats


* However if I add a single print statement in the setup() function, then that print statement is repeatedly executed (strange) and the output is garbled.


void setup ()



Serial.println("Girino ready");

Serial.println(" X1 We're outside the loop!! XD"); //This is the line we added.




Here is our output;


Girino ready

X# setup()

Girino# setup()

Girino : etup(# setup()

Girino read# setup()

Girino# setup()


Girino #######....//pounds forever.


So as you can see the setup is printed repeatedly which should only happen once.

Any help is appreciated.

here are my system & software specs:

MacBook Pro, 12-inch, Early 2011

Processor 2.3 GHz Intel Core i5

Memory 4 GB 1333 MHz DDR3

Graphics Intel HD Graphics 3000 384 MB

We are using Arduino Uno SMD edition, software version 1.0.5

Software OS X 10.9.3 (13D65)


Kerveros5 months ago

Hello, this is nice work, i have a question, have you full schematics?

snoop9116 months ago

What are your thoughts on displaying the data? Any front-end GUI you like? There seems to be so many open source options for developing GUIs ( Juice, GTK+, wxWidgets, Feathers UI, Chico UI/JQuery, etc)... example, the PulseView logic analyzer software uses sigrok/qt.

On the backend, is the serial protocol to talk to the frontend much different than firmata? Hopefully it's a serial protocol that it's easily ported to any microcontroller with a uart!

arthujt11 months ago
Any help please?
The Huntron(octopus circuit) has been a staple on most test benchs for years(me? >40years)It uses a a transformer to cause a 60hz signal and when fed thru a three resistor network, (google: octopus circuit),then is applied to X,Y (horizontal,vertical direct inputs.) This allows the pinpointing of discrete or IC defects or damaged devices,including resistors,and capacitors.This saves alot of time troubleshooting as the circuit can be tested dead. And the device doesnt have to be unsoldered(incircuit)
I looked at some android apps , and no XY functions. Can you take the timeframing out of the picture and compare two inputs directly to each other ? If you generate a pwm(60hz)send it out and return thru another input, the result can be compared to an internal (60hz) and displayed in a horizontal vs vertical scene., just place the resistors inbetween and some wiring to test devices with and you eliminate the outside source. Or just run two inputs and use the outside coil(transformer)to gen the 60hz.
kooth1 year ago
Awesome Instructables! Very well done!
ivansouza1 year ago
Nice Work!!! Maybe this could help you in this great project...
Wow, excellently well explained Christiano--I feel I've already learned so much just reading through this in the library, and I haven't even started building! It really ties together the material I'm learning in EE, in a tangible & actionable manner. Keep up the good work!
dinoi1 year ago
Great work, but I have troubles to get it run. Could you please explain the Hardware mapping on your schematic:

ADC:1 is Analog 0 on Arduino,
PWM:1 is Analog3

but where to go with AnalogComparator:1 and Threshold:1?

Thanks a lot
I did something similar, I sent out sensor values to serial port in csv formate, I used GTK term, and logged the data in a file, that file was read at the same time by KST (an awesome plotting software) to plot the data. It has a good gui and many other options, I'm trying to make a plugin for kst that will make this process simple.
Nanico1 year ago
Can you explain how to use dual channel? What is the best way to switch from 1 ch to other
Caffeinomane (author)  Nanico1 year ago
Well if you want to use two channels at the same time the acquisition rate will go down, probably more than a factor of 2.
Given that the Arduino has only one ADC you must alternatively feed to the ADC your signals. This means that you have to use the multiplexer (see step 8). At each iteration you have to:
- Read Ch 1 with the ADC
- Switch to Ch 2
- Read Ch 2
- Switch back to Ch 1
Plus doubling the number of channels you halve the amount of available memory, because you have to store two numbers at each iteration.
konsumer1 year ago
Very informative. I am the maker of arduinoscope, which is one of the Processing scopes you mentioned. Although, the original goal of that project was to make it extremely accessible to non-tech people (I used it for teaching electronics and hardware hacking.) I think we could add some of these features to that project (especially the Arduino firmware.) I don't really like Processing (or java, which arduinoscope is written in) and would be happy to switch to something else, if it could remain fairly easy for a non-programmer/electronics newb to get their hands on and modify. I started work on node.js to make a simple GUI, but Python also seems like a good candidate. I have moved the simple serial Arduino backend (sort of similar to the code pointed out, but you are exaggerating a bit, at least in my case) to use Firmata, to get myself out of the business of maintaining the firmware, and introduce new users to the awesome Firmata library. I'd be happy to move to a more performant Arduino firmware, especially if you want to maintain that part, and offer your Girino as a "fancy" version, in terms of hardware. Do you have speed stats? How much of this can be done without adding custom hardware, so people can do it all in soft/firmware?
Caffeinomane (author)  konsumer1 year ago
Thank you for your offer! Right now I am in the middle of the writing of a thesis, so I can not dedicate time on this project. When I am done with this thesis I will surely contact you to start this collaboration.
MGreatwolf1 year ago
I am somewhat new to this so forgive the question. I was reviewing your code and found the following line in it:
ADMUX |= ( ADCPIN & 0x07 );
unfortunately I am unable to locate ADCPIN in the datasheet or any of the source files provided by the Arduino developers. I like your solution and would like to dig into it a little deeper. Could you please provide some additional detail regarding ADCPIN? What it refers to and so on...Thanks for what appears to be a lot of work documenting this instructable.
Caffeinomane (author)  MGreatwolf1 year ago
Do not worry. If you look at the header file Girino.h you can see the definition:
#define ADCPIN 0
It refers to the ADC pin number that I used for the data acquisition.
aspify1 year ago
is the source code done in the arduino sketch editor or was it done in C++ code on another compiler? Just curious...thanks
Caffeinomane (author)  aspify1 year ago
Well I usually code with VIM so I basically wrote the code with VIM and then opened and compiled it with the arduino IDE.
a.flux1 year ago
Thank you very much for this project! That's exactly what I was looking for. I think I will write the Qt/Qwt interface as soon as I'm done with the soldering.

Any recent update to the schemes?

Caffeinomane (author)  a.flux1 year ago
Thank you!

No, there have not been any updates so far. I was planning to work more on this project, but some work problem denied that and are still denying.

I am still considering the idea of putting this project somewhere like Sourceforge.
Nanico1 year ago
Great work Caffeinomane!!! I love your project.
Can I use a LCD T6963c and use with girino? I have one and it run at 6 Mhz, and i want to make your project portable. Can you help me with the code for that? My ideia is to have 2 channel, but not every time.
Thank you
privatier2 years ago
For an alternative implementation of an oscilloscope, which uses an Arduino for data acquisition, please have a look at LXARDOSCOPE, available from Sourceforge. There is also a section on an investigation into the accuracy of the ADC; it includes schematics for a preamplifier which works from the same 5V supply as the Arduino.
Redsic2 years ago

This scope is great, my question though is…
This Oscilloscope is only able to read 0 -5v ? Is there anyway to Increase this ?
I know adding a resistor can make this go up to like 0-48+volts but reduces it's accuracy.

This beats the other Arduino scopes I tried hand's down.
I think this is the best DIY scope out there,
On IDE maybe you could steal the IDE from lxardoscope on Sourceforge.
I get what your saying on the power it can be powered from 12v, but you RECOMMEND 5 Volts as that's what the Ardino uses...

I really like this, not because it is a really great and simple scope with a really small footprint space wise...
but simply because of it's growth potential...

Just an Idea... for most people growing an Interest in the field.. space and initial hardware outlay cost's are an issue...

I was recently lucky enough to win a great old oscilloscope, function generator multimeter and regulated power supply for pretty cheap... second hand
and when I say cheap... I mean a few hundred pounds...
and they pretty much take up almost Half my workbench space wise.. even stacking the power supply and function generator on-top of the Oscilloscope.

This Scope is set to be the cheapest and smallest space wise...
You could combine more into this, with an Arduino mega maybe for more inputs you could build in a simple Function generator... a Multi-meter, and design to put in your own regulated power supply....
all with one credit card sized board, with a bread board and some components, you could make a PCB CNC design layout and sell them for great profit, and great value saving the average enthusiast beginner hundreds of pounds, and ton's of desk space, so they can take their projects from the garage workbench to the study desk...
then to add on a Raspberry PI 25£ credit card PC with a customized distribution with Arduino IDE etc. or a cheap 7” android capacitive touch pad with apps.
You now have an entire workbench with a design IDE, with all the tools capable of operating off a 12 volt battery... powered by wall/solar panels, and all fit in one little box smaller than your average Oscilloscope able to fit on any desk, small enough that the wife does not throw it out !
The applications could be endless...
But this project has a lot of room for Growth... and If you highlight it's growth potential... there will be a lot more interest... and a lot more people building these, and making cut's with components able to be sourced cheaply in many countries...
You will have a following and be set for life.
Schools/Universities will want this, what better way to learn than to build your own test equipment…
Not to mention cost saving’s, Saving each school from forking out thousands per each lab desk, to a mere hundred or so pounds, making education affordable !
but keep it open source please, and make the commission of donations and official branded boards, Which people will want to have...
If your keen to go down that Path, I am keen to help.
From a Automation/Integration/Programmer/IT specialist dabbling in electronics
Redsic Redsic2 years ago


Simple Logic Analyzer


Waveform Generator

Voltage Regulator

All in the same box, with say a Raspberry PI, Touchscreen/LCD, and a Lead acid Battery, = Super low cost full lab in one little box, Ideal for starters and beginners.
hoppy7772 years ago
Build an adruino signal generator. It ought to be easy to generate different wave forms.

womai2 years ago
One thing to be careful about: If you supply the op-amp with +/-12V it can drive almost as much into your Arduino - which will most likely kill the latter! Would be a good idea to add a series resistor after the last op-amp stage, and behind that two clamping diodes (Schottky type) going to 0V and 5V, respectively.
1-40 of 55Next »