0

I am using Arduino Mega 2560 to sample and serially send a square wave. I am using Processing 3.3.6 for logging the data to .csv file. I am receiving about 6k samples at the moment. When I try sampling a square wave, min= 0V, max=3V at 200Hz, the number of samples at the two amplitudes(at 0 and 3V) are not at all close by. What could be going wrong?

This is my Processing code:

//import the required libraries
import processing.serial.*;

Serial mySerial;
Table table;
String filename;

void setup()
{ //print(0);
  //set mySerial to listen on COM port 4 at 1000000 baud
  mySerial = new Serial(this, "COM4", 1000000);

  table = new Table();
  //add a column header "Data" for the collected data
  table.addColumn("Data");
  //add a column header "Time" and "Date" for a timestamp to each data entry
  table.addColumn("Time");
  table.addColumn("Date");
}

void draw()
{ print(1); 
  //variables called each time a new data entry is received
  int d = day();
  int m = month();
  int y = year();
  int h = hour();
  int min = minute();
  int s = second();
  //int s_prev=0;
  char d1 = 'a';

  if(mySerial.available() > 0)
  { //print(2);

    //set the value recieved as a String
    String value = mySerial.readString();
    //check to make sure there is a value
    if(value != null)
    { 
      String[] parts = value.split("x"); //returns an array with the 2 parts

      //print(parts);
      //print('\n');
      for(int i=0;i<parts.length;i++)
      { 

        String Part = parts[i];
        TableRow newRow = table.addRow();
        //place the new row and value under the "Data" column
        newRow.setString("Data", Part);
        //place the new row and time under the "Time" column
        newRow.setString("Time", str(h) + ":" + str(min) + ":" + str(s));
        //place the new row and date under the "Date" column
        newRow.setString("Date", str(s + 100));// + "/" + str(m) + "/" + str(y));
      }
    }
  }
print(4);}

void keyPressed()
{ print(5);
  //variables used for the filename timestamp
  int d = day();
  int m = month();
  int h = hour();
  int min = minute();
  int s = second();
  //variable as string under the data folder set as (mm-dd--hh-min-s.csv)
  filename = "data/" + str(m) + "-" + str(d) + "--" + str(h) + "-" + str(min) + "-" + str(s) + ".csv";
  //save as a table in csv format(data/table - data folder name table)
  saveTable(table, filename);
  exit();
}

This is my arduino code:

int val[2000];
void setup()
{
  Serial.begin(250000);

  //ADCSRA = 0;             // clear ADCSRA register
  //ADCSRB = 0;             // clear ADCSRB register
  ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear prescaler bits
  //ADCSRA |= bit (ADPS0);                               //   2  
  ADCSRA |= bit (ADPS1);                               //   4  
  //ADCSRA |= bit (ADPS0) | bit (ADPS1);                 //   8  
  //ADCSRA |= bit (ADPS2);                               //  16 
  //ADCSRA |= bit (ADPS0) | bit (ADPS2);                 //  32 
  //ADCSRA |= bit (ADPS1) | bit (ADPS2);                 //  64 
  //ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2);   // 128
  //pinMode(A0, INPUT);

}

void loop()
{
  for(int i=0; i<2000; i++) {
    val[i] = analogRead(A0);
  }
  for(int i=0;i<2000;i++){
    Serial.print(val[i]);
    Serial.print('x');
  }

}
2
  • Why have you asked two questions about this in quick succession?
    – Nick Gammon
    Commented Apr 5, 2018 at 10:59
  • In the previous one, I wanted to know about sampling and sending faster. Here, I want to know if I am sampling correctly. Commented Apr 5, 2018 at 12:38

1 Answer 1

0

You are doing 2000 samples really close together in rapid succession with no concept of time between them, then you are spending a considerable amount of time sending that data through serial.

That's not how you sample signals.

Instead, you need to set up some kind of time-based periodic sampling system, either through a timer interrupt or some other facility provided by the ADC (read the datasheet to see what interrupts the ADC can generate and what sample trigger sources there are) which runs completely asynchronously. Then when (and only when) a sample set has been captured do you send that data through serial.

If your sampling takes longer than your sending through serial (unlikely) and you have the memory for it you can set up two buffers and "ping-pong" between them so you are sampling at the same time as sending. Otherwise, all you will be able to do is capture a short window of data and then send it afterwards, so you get short bursts of samples.

4
  • Thanks. I see where I went wrong. Would using the free running mode of the ADC serve my purpose better? Commented Apr 5, 2018 at 12:40
  • As long as you attach an interrupt to it to read each sample, yes.
    – Majenko
    Commented Apr 5, 2018 at 12:41
  • Suppose I take a sample and send it serially within the ISR function, that would make all my samples equally spaced in time right? Commented Apr 5, 2018 at 12:45
  • As long as the serial sending takes less time than the time between samples, possibly. Sending serial from inside interrupts takes special care since it itself is interrupt driven.
    – Majenko
    Commented Apr 5, 2018 at 12:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.