I put together a little oscilloscope based on an arduino duemilanove as a first project to learn about how the system works. There's plenty of polishing to be done, but it mostly works and runs at about 5kHz with the default setting.

It uses a counter interrupt as a time base and just uses the top 8 bits of the ADC to give 8-bit resolution. The Arduino reads analog input 0 every time the interrupt fires and sends the value over USB to a program running in Processing. The Processing code scans the incoming data to see when it passes through a trigger level. Once the trigger level is detected it starts saving the incoming data and then plots it to the screen. If too much time goes by it just plots what data it has so you get a 'live' view of what is going on at the input pin. Clicking anywhere on the screen sets the trigger level to the mouse location.

The Arduino code contains one special line, "#define TEST_MODE". If you leave this line as-is the Arduino ignores the analog input and sends a mathematically generated ramp wave which is nice for debugging the Processing code. Comment this line out and you will get the analog input pin values instead.

The Processing code has a few debugging items too. A white circle in the upper left-hand corner blinks when the frame updates. If this isn't blinking something is hanging in the code. There is another green circle that appears if the frame was started by a trigger event, and a red circle appears if the frame was started without a trigger event. A horizontal purple line shows where the trigger level is.

Welp, it's good enough for now and I'm sick of reading datasheets. Thanks to these forums and the Arduino team for all the great help!

e.

Known Bugs1) The frames in Processing sometimes do not update smoothly. I think the root of this problem is that the loops that read the serial port are too short and run the CPU to 100% constantly polling for new input. Eventually the CPU wanders off to handle its other tasks and the screen hangs for a minute. There is likely a better way to do this polling.

2) Values of 5V and 0V input can run the scope trace off the screen. This is kind of annoying, but just needs a better scaling method.

To Do1) It would be nice to have a pre-trigger, just like on a real oscilloscope, that would let you see a bit of the data that came in before the trigger event.

2) I think the sampling rate can still be faster. Maybe running the ADC on self-triggering mode and fixing the choking issue with the Processing code would help. If anyone can point me to a good guide on setting the ADC to free-running mode I'd greatly appreciate it.

3) It would be cool to add the ability for Processing to change the sampling rate from the UI by sending messages to the Arduino.

Serial inPort; // the port to read fromint BAUD_RATE = 115200; // set baud rate here, needs to be the same value as in the arduino codeint BUFFER_SIZE=200; // data buffer sizeint GRIDS=10; // number of grids to drawint inVal; // y-data read in from the arduinoint lastVal; // old value of y-dataint[] yVals = new int[BUFFER_SIZE]; // y-data buffer, scaled to the screen sizeint[] xVals = new int[BUFFER_SIZE]; // x-data buffer, scaled to the screen sizeint trigger; // trigger, when the incoming data passes this value a frame startsint timeOut; // if no trigger is detected by timeOut samples, plot what is at input portint i; // counterboolean blinker; // blinks a light on each frame update so you know when program is running boolean noTrigger; // true until trigger is detectedboolean noTimeOut; // true until timeout runs out if no trigger is found first

If you want a faster sampling rate, how about repeatedly calling analogRead in loop instead of using an interrupt?

I used the timer/interrupt setup so that eventually the user can set the sampling rate to some arbitrary number (1kHz, 5kHz, 10kHz, etc) and have it be somewhat accurate. Hopefully this will mimic the behavior of a 'real' oscilloscope better.

Plus it was an excuse to learn how to do interrupts.

Quote

nice work, really love this idea. wish i had the skills to help you with it.

i tried your setup with a standard IR receiver module but can't see any results. any ideas?

It runs on 38khz. Maybe that's too fast?

For the sake of simplicity I pinned the sampling rate at 5kHz until the serial interface with Processing works a bit better, so I imagine that might be one problem. Also, there is a scaling issue where values of 5V and 0V don't display correctly - if your module is flipping between those two points rapidly you might just see some vertical lines.

Hopefully I can fix some of these things when I get a bit of time to play with it again, check back in a week or so and it may be working better.

I used the timer/interrupt setup so that eventually the user can set the sampling rate to some arbitrary number (1kHz, 5kHz, 10kHz, etc) and have it be somewhat accurate. Hopefully this will mimic the behavior of a 'real' oscilloscope better.

That works for the slower sampling rates but because the overhead in the interrupt handler may get in the way when the sampling rate is fast, why not do a simple test and see how fast you can go with just analogReads and the serial print. If you can get usefully higher sampling rates, then you could use the interrupts for the slower modes and the non-interrupt version for higher speed. You would probably need to pad each analogRead/Serial.print with some delay to round out the sampling rate to a decade boundary.

But it may be that that delays in serial.print are a bigger factor than the interrupts - but it could be intersting to find out

i tried to pair your processing script with the infrared analyzer. one issue i have is that the arduino sends out pairs of data with a time index and a value.any suggestions how to send a pair of values to processing?

My bad, I missed the second parameter BYTE.I just assumed he is sending the full precision 10bits of the Analog value.

Looking again into code, as it is written it would result in truncated values being sent out. Check following code from serial.print() library where long is type casted as char, which implies only bottom 8 bits are sent out.

If I am not mistaken doesn't one ADC read take 100us? So the real limitation then becomes the reading. At 100us, the sampling rate is 10khz. Plus the overhead for sending (I actually did an experiment and was able to use a 500,000 baud rate, yes 500k, baud rates depend on the Crystal Frequency (8khz in my case), certain frequency conflict with certain baud rates) .

I was doing a forever loop with a delay at the end (to sync my reads) I was able to sample every 342us (2.924khz). Anything lower would fail. (1 ADC reading, sending 2 Bytes, 2 Calls to Microseconds, 1 Delay Statement).

As far as sending on Serial, the limitation I believe is the overhead for initializing the connection internally (interrupts etc maybe?)

***HAS ANYONE FIGURED OUT A WAY TO OBTAIN A HIGHER RATE? I was thinking of getting a 16mhz model, but I can only imagine this helping out slightly. (the 100us read is still present).

I've tried several different versions of oscilloscopes from around here including the google code one, simple and tiny one but I'm getting the same trace "noise" on all channels.I am using a Pro Mini with FTDI cable and seem to get noise. It seems to be related to the USB but is not transmission or receiving or Raw voltage or Vcc. I can only assume it to be a combination or interference from the pro mini circuit as the only thing i have added is the lead for probing.Any ideas on this frustration?

I've tried several different versions of oscilloscopes from around here including the google code one, simple and tiny one but I'm getting the same trace "noise" on all channels.I am using a Pro Mini with FTDI cable and seem to get noise. It seems to be related to the USB but is not transmission or receiving or Raw voltage or Vcc. I can only assume it to be a combination or interference from the pro mini circuit as the only thing i have added is the lead for probing.

maybe you could show what you mean by "noise".. I would have thought that anything in the USB circuit would be too high frequency to show up in the signal. what does your proble look line? have you tried grounding or shielding it?

There's absolutely no noise induced on USB cable (digital). BUT you might have leaking current to ADC inputs. To overcome that, try the following tips:

* Have a good ground connected on ADC cabling.* Disable every other ADC input. Also don't use ADC gain (if Mega).* Despite datasheet saying input impedance is 100M, it is not. I am not sure what's it impedance is. But the idea is to match it on your input (if you have a 1M ohm impedance, make sure your input is also 1M ohm). Also use a stable ADC ref value, this is very very important. If possible, use the internal 1.1V source. Why do I say input impedance is not that high? Simple - connect VCC to ADC input and watch your controller heat *a lot*. But might be an issue with the muxer only.

I never used a tiny, but should not differ that much. I've a clone actually, but did not use it (yet).

Wondering : if you tie your ADC input to ground, using a 100 ohm resistor, what do you get ? Noise ? And if directly connected to ground ? And if using a 100Kohm ?