2
\$\begingroup\$

I'm working on a project to build an oscilloscope using the Arduino Mega2560. I've built the system using an 128x160 display, and I'm having difficulty showing a range of frequencies on the display.

The system I have developed measures the input signal with a 1ms delay between each measurement, doing this 120 times placing each reading in an array. I found I have to use a 1ms delay else it captures low frequencies too fast and will only show parts of waveform. Using this system, the scope only measures up to about 400Hz before Nyquist sets in and the waveform becomes distorted.

I measure frequency (top left) by checking the array and finding how many times the signal crossed 0. To stop the signal flying around the screen, i find the first value when it crossed 0 and draw the signal from there. Only 74 values from the 120 array are displayed.

Is there an mathematical way from the information given such that if frequency is above 'x' change delay, such that the system could auto range and measure upto 100kHz and display the signal on screen, is this possible?

enter image description here

\$\endgroup\$
  • 2
    \$\begingroup\$ Oscilloscopes usually have switchable timebases - the user determines how much time the display represents. You will not be able to get fast sampling using your current method. You can get to maybe 10000 samples per second using the Arduino libraries. You certainly won't get to the 200000 samples per second needed to capture a 100kHz signal. \$\endgroup\$ – JRE Mar 5 '18 at 20:14
  • \$\begingroup\$ Yes, I understand. I am wondering if this can be done automatically with the given setup, like the ossiloscopes auto ranging feature - edited questioned to include term 'autoranging'. \$\endgroup\$ – user160063 Mar 5 '18 at 20:18
  • \$\begingroup\$ How will you do it automatically? If you sample too slowly, you can't detect the higher frequencies. If you sample too fast, you run out of memory and can't detect the lower frequencies. \$\endgroup\$ – JRE Mar 5 '18 at 20:23
  • \$\begingroup\$ And, like I said, the Arduino just isn't capable of high sampling rates. \$\endgroup\$ – JRE Mar 5 '18 at 20:24
4
\$\begingroup\$

This is a problem with many aspects to it, but at the very minimum, you should not be tying the number of samples you take to the resolution of your display. Instead, take samples as fast as you can or, if you have an analog anti-aliasing filter (as you should), at or above the Nyquist rate for the filter's bandwidth.

Then, when you paint the samples you have taken on the screen, you can choose how to do so. Some simple to implement ways:

  • For each column of the screen, find all the samples which fall into that range, and fill from the minimum level to the maximum level of those samples. This will avoid creating additional aliasing, and is a common display technique in audio editors.
  • Draw all the samples individually as points, no matter how many points end up on the same column. This shows more detail but requires more interpretation from the user.

Besides avoiding unnecessary aliasing, separating sampling and display also allows you to implement single-shot capture followed by zooming/panning the view, which will help with the usability of your low-resolution display.


As to auto-ranging: once you have sampled as best you can, you can then apply your frequency counting or whatever other algorithm to that data to choose a starting zoom. But if you sample slowly then you have already thrown out data, and that's a problem. (You might have a problem with storing enough data to work over a wide frequency range without external RAM, though.)


Depending on your goals, it might be an interesting exercise to implement an oscilloscope on a PC using sound-card input. That way, you can play with signal processing and painting algorithms with fewer resource constraints; and USB sound-cards can be readily found with up to 192 kHz sampling rate (though often AC-coupled). Then you can take what you learned and figure out how to fit it onto the Arduino.

\$\endgroup\$
0
\$\begingroup\$

With a horizontal resolution of 160 pixels you want at least 2.5 samples per max sine wave frequency depending on trigger sync to prevent aliasing. That defines the number of zero crossings per frame capture. Unfortunately your pixel resolution is low.

but if your ADC is at least 2.5x faster than input spectrum BW then auto ranging X axis is possible if you can display the scale. However for vertical accuracy 10x samples per sine is needed.

Just the opposite of DMM auto ranging, which checks for overflow, you start at the maximum sampling rate and count zero crossings and decrement sampling rate.

I recall the TD autocal displayed 4 cycles of the fundamental. In your example there are 4 bursts of 10 cycles so 1 burst of 10 cycles might be ideal. The triggering is trick with decimation, and filtering to find the fundamental.

Early TEK's used PLL's to anti alias the refresh rate but capture the fundamental rate. A crude display will have too much trigger jitter.

This page indicates 100 KHz sampling rate when logging to a SD card and more with an external ADC. 8-bit ADC values at 100,000 samples per second. The estimated accuracy is 7.3 ENOB

https://forums.adafruit.com/viewtopic.php?f=31&t=30557

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy