Oscilloscope

I have played with arduino and processing for a while and have made up a (very) simple oscilloscope which seems to be fine for up to about 50kHz but I would like to do better. The main problem is the limitation of analogread even after the trick of altering register settings of the ATMega328 as below:

byte bytevalue;
int dtime=5;
void setup()
{
  bitClear(ADCSRA,ADPS0);
  bitClear(ADCSRA,ADPS1);
  bitSet(ADCSRA,ADPS2);
  Serial.begin(115200);
}

void loop()
{
  
  byteValue = analogRead(0)/4;
  Serial.write(byteValue);
 delayMicroseconds(dtime);

}

What I am wondering is if I could use the following ADC: http://uk.rs-online.com/web/p/general-purpose-adcs/7096777/

which looks fairly easy to set up ( OTOH I have NO experience using these ) If the arduino can read a whole bunch of digital inputs in one go and then just do a Serial.write I am thinking it might be possible to get a better throughput. Any thoughts as to whether this is practical?

Think about storing the reading along with a time stamp and then sending them in batches of 100 or 200 hundred to the PC for plotting. This wont give you a continuous display but will give you more detail.

Mark

Mark, Are you suggesting I do this with the current setup? If so can you give me some idea how I could work out how much faster this would be? Also what do you think about what I suggested?

Are you really outputting 8-bit samples over a 115200 bps serial link at 50 KHz? The numbers don't seem to add up.

Perhaps I am calculating it wrongly. I've posted the arduino code already so here is the processing code:

import processing.serial.*;
Serial myport; // Create object from Serial class
int val; // Data received from the serial port
int ypos = 0;
int xpos;
int divider = 5;
int topend = 690;
int[] lastpos = new int[3005];
PFont font;
int offset=0;


void setup() {
size(1260, 690);
strokeWeight(1);
//line(0,430,1200, 430);
//line(0,220,1200, 220);

font = loadFont("AndaleMono-28.vlw");
textFont(font);
pagesetup();
String arduinoPort = Serial.list()[0];
myport = new Serial(this, arduinoPort, 115200);
myport.bufferUntil('\n');
}
void draw() 
{
}

void pagesetup()
{
background(225);
line(0,230,1200, 230);
line(0,460,1200, 460);
fill(255);
rect( 1000,0, 1000,690);
fill(0);
text(" Norm's scope", 1000, 30, 1000, 100);
line(1000,115,1010,115);
text(" 2.5 volts", 1005, 100, 1005,100);
line(1000,345,1010,345);
text(" 2.5 volts", 1005, 330, 1005,330);
line(1000,575,1010,575);
text(" 2.5 volts", 1005, 560, 1005,560);
}

void serialEvent(Serial myport)
{
String inString = myport.readStringUntil( '\n' );

if(inString != null )
{
inString = trim(inString);
xpos = int(inString)/divider;
if (lastpos[offset] != 230 && lastpos[offset] != 460)
{
stroke(255);
point(ypos, topend - lastpos[offset+1]);
}
stroke(0);
point(ypos, topend - xpos );
lastpos[offset]= xpos;
ypos += 1;

if(ypos >999 && topend==690)
{
ypos=0;
topend= 460;
//offset=1000;
}

if(ypos >999 && topend==460)
{
ypos=0;
topend= 230;
//offset=1000;
}


if(ypos >999 && topend==230)
{
ypos=0;
topend= 690;
//offset=0;
}
offset++;
if(offset>3000)
{
  offset=0;
}
}

}

I usually am wrong :disappointed_relieved:

The best you could manage without compression would be 11 520 eight bit samples per second.

Where does the value of 50KHz you mentioned come from?

You have three sources of delay in your program

  1. The time it takes to read the ADC.

  2. The overhead of the call to analogRead().

  3. The time taken for the call to Serial and the short delay() you have inserted.

The batch method I sugested removes the delays caused by Serial and the need to wait while data is output.

From the datasheet we have

A normal conversion takes 13 ADC clock cycles. The first conversion after the ADC is switched
on (ADEN in ADCSRA is set) takes 25 ADC clock cycles in order to initialize the analog circuitry.

So with my read an store method and some very carefully written code you may get as much as 1M samples per second but only in short bursts. There are some bits in the spec that lead me to think that it may even be possible to beat that!.

Mark

PS Not had chance to look at the ADC chip you linked to yet.

M

So with my read an store method and some very carefully written code you may get as much as 1M samples per second

With a minimum 13us conversion time, that would be efficient code indeed.

With a minimum 13us conversion time, that would be efficient code indeed.

Yep, I miss read ADC clock cycles as CPU clock cycles :blush:.

now I need to wrap my head around this (from the datasheet)

• 13 - 260 ?s Conversion Time
• Up to 76.9 kSPS (Up to 15 kSPS at Maximum Resolution)

as the two sets of figures don’t match up.

Mark

OK so now I’ve got my head around all the figures and written some test code which confirms them. You could get the 76.9 kSPS if you write your own version of analogRead(). Here’s my quick and dirty burst reading code.

int value[256];
int i;
unsigned long startTime;
unsigned long endTime;
int timePerRead;
int readsPerSecond;
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  startTime =micros();
  for (i=0;i<=255;i++){
    value[i] = analogRead(0);
  }
  endTime = micros();

  // write data
/*  for (i=0;i<=255;i++){
    Serial.print("i = ");
    Serial.print(i);
    Serial.print(" value = ");
    Serial.println(value[i]);
  }*/

  Serial.print("start time = ");
  Serial.println(startTime);
  Serial.print("end  time = ");
  Serial.println(endTime);
  Serial.print("Total time = ");
  Serial.println(endTime - startTime);
  timePerRead = (endTime - startTime)/256;
  Serial.print("Time per read = ");
  Serial.println(timePerRead);
  Serial.print("Reads per second = ");
  readsPerSecond = 1000000UL/((endTime - startTime)/256);
  Serial.println(readsPerSecond);
  delay(10000);

}

Something interesting to look at...

http://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/

@cr0sh Had a look at the code and have to say it is very thorough.

I have been looking at this again and thought about doing the bit about speeding up the ADC but then writing the value to 8 digital pins as a direct access to a port instead of using the Serial.write.

To get the results into the computer I am thinking of buying a USB <-> parallel lead. I remember about 25 years ago a way of using the parallel port to control external kit. I think this might be a way of getting more throughput.
Or maybe it would be easy enough to use the Raspberry Pi as the PC. No need for the USB/Parallel lead yhen.