Fast, Portable and Affordable Oscilloscope and Inductance Meter

Similar projects worth following
Don't be deceived by its small size. This little beast has an inductance meter and a oscilloscope with sampling rate of 1.7 MS/s, based on a STM32 running at 72MHz. Frequency, voltage and duty cycle information are included. As a bonus, you get temperature and pressure sensing.

The main goal when I built this was to have a simple to use yet capable scope to view oscillations and an inductance meter to learn about oscillator circuits.

Commercial versions of these tools have a high price that is prohibitive to many of us, so the more affordable and open source approach of this project may allow more and more makers and hackers to explore this wonderful part of electronics.

Building our multiScope isn't hard from the hardware perspective, it is in the software that most magic happens. The base of this project was the STM32-O-Scope (which is also based on another scope), from which I got the DMA code. Without it, our scope wouldn't be so fast.

The STM32F103C8T6 is a 32bit ARM microcontroller (with a quite long name) that has higher clock and ADC resolution than any AVR based Arduino, but is still cheaper than them. Another great thing is that you may program it using the good old Arduino IDE.

I've chosen a touch screen dispay for multiScope to keep user interaction simple and flexible. With these same principles in mind, the input signal is connected to a voltage divider that can be replaced in order to reduce voltage to 3.3V, the maximum value STM32 will safely handle.

Our inductance meter is based on LM339 and a simple LC circuit whose resonant frequency we measure to get the unknown L value.

You may adapt multiScope to your needs. As I had a bmp180 lying around, it was included as an extra feature, but it's your choice. If you don't want it or want to include another kind of sensor, just change a few lines of code.

This file contains 3 Adafruit libraries: BMP180, GFX and ILI9341. This last one was patched to the display I used, while the others are ordinary libraries.

x-zip-compressed - 778.40 kB - 04/15/2017 at 17:44



Latest code version with automatic attenuator detection and corrected time base

ino - 38.98 kB - 04/15/2017 at 17:43



A sketch to test the display wiring, slightly modified version of Adafruit's original example

ino - 5.61 kB - 04/02/2017 at 21:11



Previous code

- 36.31 kB - 03/31/2017 at 22:44


  • 1 × STM32F103C8T6 minimal dev. board (aka "blue pill")
  • 1 × 3.3V USB/Serial adapter I used FT232RL. It's for programming the MCU
  • 1 × 2.4" LCD TFT touch screen display You'll find it by searching "2.4 tft lcd" on eBay
  • 1 × BMP180 For pressure and temperature sensing
  • 1 × A box or enclosure As you might have seen, mine was a pretty toy car

View all 16 components

  • Negative voltage support

    Vítor Barbosa04/15/2017 at 18:52 0 comments

    I decided to post it on instructables too, and while tinkering with the scope I ended up adding support to negative voltages and offset. Here's a pic of 120VAC input from the mains:

    I've uploaded the new code and plan to properly update the instructions here later, but in the meantime, anyone interested is welcome to check the project there.

View project log

  • 1
    Step 1

    Add STM32 support to the Arduino IDE

    Thanks to the guys from we are able to program the STM32 family using Arduino. What you need to do is very simple:

    • Install Arduino SAMD Boards package with the Arduino Boards Manager
    • Download or clone the Arduino_STM32 into the Arduino/hardware folder
    • Open the IDE, select your board (Generic STM32F103C series if it's the blue or red pill) and Serial as Upload Method to program using the USB-Serial adapter (like FT232R)

    Connect the board by following my little sketch. You may test it with the ordinay Blink code, just note that the onboard led is on PC13 and that you will need to change the position of the first jumper to switch between Run and Program modes.

  • 2
    Step 2

    Display and power source

    Once we've made sure the main board is working, let's add the touch screen. The wiring is described in my drawing and also in the sketch code.

    Some pictures of my version:

    I've put the regulator(7805), battery(7.2V li-ion) and switch together. The jumper cables connect to the display 5V and GND pins directlty.

    This is the full scope, so just pay attention to the blue pill and display.I know... it's really messy. That's why we have a nice cover to hide everything!

  • 3
    Step 3

    Test the display

    Before proceeding, you should test the display and touch to see if everything is working.

    The patched TFT library contains code that might not work well with the default Wire library due to pin conflict, so let's edit a few lines to avoid trouble:

    • Go to Arduino\hardware\Arduino_STM32\STM32F1\libraries\Wire
    • Open Wire.h with a text editor you like and look for #define SDA
    • Make it like this:
    #define SDA PC15
    #define SCL PC14
    • Save the file. Now SDA is on PC15 and SCL is on PC14.

    I've modified the original example a little, and so may you to adjust the touch sensitivity constants. Upload it (the file is lcd_touch_paint.ino) and you should get something like this (the picture is Adafruit's):

View all 7 instructions

Enjoy this project?



Osman Mazinov wrote 04/14/2020 at 06:18 point

Hi! Thanks for your project! I try original O-Scope project without touchscreen, but got some problem:

I used newest /Arduino_STM32 Core and downloaded

/STM32-O-Scope sketch compiled and uploaded it to the device via UART from 0x800000 address. Then I started the device. The grid and coordinate lines were displayed on the screen. Also on the screen were displayed inscriptions below 0.0 uS/Sample etc... But any noise or pulse signal from PB1 on my Probe. Why the chart is not drawn?

  Are you sure? yes | no

nikjayswal wrote 03/18/2019 at 18:45 point

my 2.4 tft showing only "White Screen dosent display anything"

  Are you sure? yes | no

PratiktoSH wrote 01/26/2019 at 04:14 point

I'm inspire to make another project based on your idea. I'm curious if it's okay to use another data & control from LCD in STM32. I find that you use pin PB15-PB8 for data pins and PA0-PA8 for control pins. But in Adafruit_ILI9341_8bit_STM.h, I can't find the pin declaration for data port. There is only declaration for control port.

  Are you sure? yes | no

andyhull wrote 06/15/2017 at 22:49 point

I love the case you have used... Mini-scope.. 

  Are you sure? yes | no

Vítor Barbosa wrote 08/27/2017 at 15:34 point

Sorry for the late reply but thanks. None of this would've been possible without your project in the first place!

  Are you sure? yes | no

ldv82 wrote 05/17/2017 at 13:33 point

Hello. I have a problem. Example lcd_touch_paint.ino Works great. And there are a lot of phantom clicks in the oscilloscope sketch. I can not choose the oscilloscope function, because another option is immediately turned on. In function readTouch() has changed if (p.z > MINPRESSURE && p.z < MAXPRESSURE). At the same time, the touchscreen does not work.

  Are you sure? yes | no

Vítor Barbosa wrote 05/17/2017 at 21:59 point

Hi! The readTouch() function of the scope sketch was changed because using p.z wasn't very good with my display. Try changing if(touchX>20) to a higher number. You may also try using touchY or reverting to p.z code. Besides, MINPRESSURE and MAXPRESSURE are constants that could be adjusted.

  Are you sure? yes | no

Jiri Bilek wrote 02/18/2018 at 07:28 point

Hi, thanks for the great app.

I am playing a bit with the code, recently. I believe that the problem with the touchpad is in reusing ADC. When I reinitialized the ADCs after taking the samples into the memory (and added initialization before sampling, obviously), the touchpad works fine. The code for reinitialization is here:

// -------------------- resetADCs
// Deinitialize ADCs to that the analogRead function can be performed. We have to restart the ADCs.
void resetADCs() {
    // stop the ADCs - needed for stabilization from the continuous mode
    ADC1->regs->CR2 &= ~1;  // ADON = 0
    ADC2->regs->CR2 &= ~1;  // ADON = 0
    delayMicroseconds(5);  // 1 uS should be enough

    ADC1->regs->CR1 &= ~0x000f0000;  // Independent mode
    ADC1->regs->CR2 &= ~(ADC_CR2_CONT | ADC_CR2_DMA);  // Set single mode and no DMA
    ADC2->regs->CR2 &= ~ADC_CR2_CONT; // ADC 2 single

    adc_set_sample_rate(ADC1, ADC_SMPR_55_5);
    adc_set_sample_rate(ADC2, ADC_SMPR_55_5);
    // start the ADCs again
    ADC1->regs->CR2 |= 1;  // ADON = 1
    ADC2->regs->CR2 |= 1;  // ADON = 1

I changed also the time axis handling (multiples of 10, 25, 50 us per div only), I plan to make onscreen touch buttons.

When my project is ready, I'll post it here.

BTW: Are you sure you can use dual fast interlaved ADC mode with longer sampling times safely? The documentation (AN3116 from ST) says "

The maximum allowed sampling time is 7 ADC clock cycles to avoid the overlap between the ADC1 and ADC2 sampling phases in the event that they convert the same channel. This means that the only allowed sampling time is 1.5 cycles."


  Are you sure? yes | no

ldv82 wrote 04/12/2017 at 07:07 point

How to determine the frequency of the signal, which is in the photo? Can you use this example? Timebase - is the price of one division?I reason so... The period takes 15 small divisions or 1,875 large. One division is now 100 uS (Timebase)? Then 1.875 * 100 = 187.5uS1/187.5=0.00533 .Then 0.00533*1000000=5333 Hz

  Are you sure? yes | no

Vítor Barbosa wrote 04/12/2017 at 11:47 point

One of the ways I found to measure frequency precisely is by using a rising of falling interrupt on the code. Tie the analog input pin to another digital input using a resistor (at least 1k, it's for protection and keeping impedance high) and count rises or falls during a second. As every time one of these happens, you have a full cycle. Then you have cycles/second = Hz.

  Are you sure? yes | no

ldv82 wrote 04/14/2017 at 19:56 point
Thank you. Did the frequency measurement according to your circuit. Everything is working.
I do not see a signal on the display at timebase = 2000 and higher.Is there any restriction?Sketch took not from you, but from the forum

  Are you sure? yes | no

Vítor Barbosa wrote 04/15/2017 at 18:31 point

Hey! Timebase should indicate how many seconds/div, but it wasn't correct in the original code. See my latest sketch. It's now working as expected.

  Are you sure? yes | no

darth_llamah wrote 04/01/2017 at 12:10 point

You may want to read the Pig-o-scope forum thread ( as there were some modifications done recently

  Are you sure? yes | no

Vítor Barbosa wrote 04/01/2017 at 22:42 point

There are some nice things indeed and they've even included a PGA before the analog input. It could certainly be used to make the scope more sensitive to weak signals.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates