How to control MCP3008 sampling rate by Arduino

Hello, my objective is to perform ADC operation by using MCP3008 chip in Arduino Mega 2560 Board and then write the ADC value into a .csv file with timestamp by using Gobetwino application.

Currently, I able to perform ADC operation as well as able to write ADC value into a .csv file by Gobetwino. However, my problem is it only produce 1 sample per second only in .csv file since my desired result is 100 samples per second or 1000 samples per second. How can I control or increase the sampling rate so that I can captures more samples in one second?

Thanks you very much and appreciate for helping. Hereby I attached my previous Arduino coding as shown in below.

// This sketch demonstrates the use of the Gobetwino commandtypes LGFIL and CPFIL

#include <SPI.h>

#define SELPIN 53 //Selection Pin 
#define DATAOUT 51//MOSI 
#define DATAIN  50//MISO 
#define SPICLOCK  52//Clock  
int readvalue; 
byte clr;

int serInLen = 25;
char serInString[25];
int logValue1=0;
int logValue2=0;
int logValue3=0;
int logValue4=0;
int logValue5=0;
int logValue6=0;
int logValue7=0;
int logValue8=0;
int result;

void setup() 
{ 
 pinMode(SELPIN, OUTPUT); 
 pinMode(DATAOUT, OUTPUT); 
 pinMode(DATAIN, INPUT); 
 pinMode(SPICLOCK, OUTPUT); 
 //disable device to start with 
 digitalWrite(SELPIN,HIGH); 
 digitalWrite(DATAOUT,LOW); 
 digitalWrite(SPICLOCK,LOW);
  
  // Setup serial comm. Initialize random function.
  Serial.begin(9600); 
  //randomSeed(analogRead(0));
 // delay(5000); 
  // Use the CPTEST copy file command to make a copy of a new empty logfile
  Serial.println("#S|CPTEST|[]#");
  readSerialString(serInString,1000);
  // There ought to be a check here for a non 0 return value indicating an error and some error handeling
} 
 
void loop() 
{ 
   //Create some random values to log to a file on the PC.  This could be sensor readings or whatever
   //but for this example it's just 3 random values
   logValue1= read_adc(1);
   logValue2= read_adc(2);
   logValue3= read_adc(3);
   logValue4= read_adc(4);
   logValue5= read_adc(5);
   logValue6= read_adc(6);
   logValue7= read_adc(7);
   logValue8= read_adc(8);
   
   logData(logValue1,logValue2,logValue3,logValue4,logValue5,logValue6,logValue7,logValue8);
   delay(500); 
}

// Send the LOGTEST command to Gobetwino the 3 random values are seperated by semicolons
 
void logData( int value1, int value2, int value3, int value4, int value5, int value6, int value7, int value8) 
{
   char buffer[5];
  
   Serial.print("#S|LOGTEST|[");
   Serial.print(", ");
   Serial.print(itoa((value1), buffer, 10));
   Serial.print(", ");
   Serial.print(itoa((value2), buffer, 10));
   Serial.print(", ");
   Serial.print(itoa((value3), buffer, 10));
   Serial.print(", ");
   Serial.print(itoa((value4), buffer, 10));
   Serial.print(", ");
   Serial.print(itoa((value5), buffer, 10));
   Serial.print(", ");
   Serial.print(itoa((value6), buffer, 10));
   Serial.print(", ");
   Serial.print(itoa((value7), buffer, 10));
   Serial.print(", ");
   Serial.print(itoa((value8), buffer, 10));
   Serial.println("]#");
   readSerialString(serInString,1000);
   // There ought to be a check here for a non 0 return value indicating an error and some error handeling
} 

//read a string from the serial and store it in an array
//you must supply the array variable - return if timeOut ms passes before the sting is read
void readSerialString (char *strArray,long timeOut) 
{
   long startTime=millis();
   int i;

   while (!Serial.available()) {
      if (millis()-startTime >= timeOut) {
         return;
      }
   }
   while (Serial.available() && i < serInLen) {
      strArray[i] = Serial.read();
      i++;
   }
}



int read_adc(int channel) //functiion prototype for Read ADC
{  
  int adcvalue = 0;
  
  byte commandbits = B11000000; //command bits - start (B7) , mode (B6), channel (B3 to B5), dont care (B0 to B2)  Note: B1 (1st bit // LSB) ; B7 (8th bit //MSB)  (Channel refer to datasheet)
  
  //allow channel selection
  commandbits|=((channel-1)<<3); // must put "|" (not one "1" symbol) 
  
  digitalWrite(SELPIN,LOW); //Select adc
  // setup bits to be written
  for (int i=7; i>=3; i--){
   digitalWrite(DATAOUT,commandbits&1<<i);  // correct instruction  Note: it means commandbits & (1<<i), do "1<<i" first. 
   //digitalWrite(DATAOUT,HIGH); //cannot use this instruction
    
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);    
  }

  digitalWrite(SPICLOCK,HIGH);    //ignores 2 null bits
  digitalWrite(SPICLOCK,LOW);
  digitalWrite(SPICLOCK,HIGH);  
  digitalWrite(SPICLOCK,LOW);

  //read bits from adc since it is ADC is 10 bits, then int i=9; i>=0; i-- ; if ADC is 12 bits, then nt i=11; i>=0; i--
  for (int i=9; i>=0; i--){
    adcvalue+=digitalRead(DATAIN)<<i;
    
    //cycle clock
    digitalWrite(SPICLOCK,HIGH);
    digitalWrite(SPICLOCK,LOW);
  }
  digitalWrite(SELPIN, HIGH); //turn off device
  return adcvalue;
}

jayfoonglw:
However, my problem is it only produce 1 sample per second only in .csv file since my desired result is 100 samples per second or 1000 samples per second. How can I control or increase the sampling rate so that I can captures more samples in one second?

For how long or how many samples ? If your answer is "continuously" then you'll need to speed up your serial communications to the PC. I've not looked deeply at your code but sending data as ASCII characters takes some time, especially at 9600 baud. That's about 1 msec per character. 10 bits can range up to 4 characters long and so that's a min of 4 msec or a max of 250 samples/sec just due to sending the data.

So the very first thing to do is find out the max baud rate (w/o too many errors) that your serial link can handle. Then if you want a really consistent “X” samples/sec, you’ll need to use a timer to trigger the A/D sampling. Right now it appears that your sampling interval is determined by how fast you can sample, process and send the data. You sample as fast as the loop() runs. The time it takes to send the data is dependent on the data itself and so your sample-sample timing can vary. Depending on how you’re using the data this may, or may not, be important.

If “X” is to be really fast you’ll need to send the data as binary, not ASCII, 2 bytes for the 10 bits, for each sample. I’m not sure how well such a scheme, if needed, will play with Gobetwino.

Tell “us” what the data is and your usage and “we” can better help you decide on the level of code complexity needed for your application.

Dear Mee_n_Mac,

Thanks you for your recommendation. Can you guide me how to perform your recommendations as well as can you provide specific Arduino Coding for increasing sampling rate?

Thanks and appreciate.

In other words…

jayfoonglw:
Can you guide me how to perform your recommendations as well as can you provide specific Arduino Coding for increasing sampling rate?

Can I ... I suppose I could. Will I ... nope. I've already got my fingers in enough pots here. Quite frankly I just don't have the free time to do what I think I'll need to do. Moreover I asked a couple of simple questions, that I'd need to know the answers to, in order for me to be your personal code monkey. You seemingly can't be bothered to answer those and that doesn't bode well for me getting deeply involved in your project.

I wold suggest you write down in a few sentences exactly what it is that you need to do along with some background info on why you’re doing it and the end goal. Then figure out what, if not in C++, it’ll take to do those sentences. “We” here can then help and advise you with the details if/when you’ve tried and can’t figure out the C++ code to implement those functions.

Using your Arduino as a single, or even multiple, channel data acquisition board isn’t all that hard. My guess, looking at the code you’ve posted, is that you’ve taken the spaghetti approach. You haven’t taken the time to try to understand the problem/project but have collected code from various people and have thrown it at the wall to see what “sticks”. This is actually a much harder (and longer) approach than being a little more methodical as I outlined above. But that’s your choice to make.

ps - do you know why I’ve said what I’ve said ? Look at this statement in your loop() code (all of 10 lines long !) …

delay(500);

C’mon now, are you seriously trying to tell me (“us”) that you’ve even bothered to try to figure out why your code runs at 1 sample/sec. Or how to make it faster ? You’ve got an explicit 0.5 sec delay in the loop, right there in the open for anyone to see. And I’ve spent all of 3 minutes looking at the code you posted. You’re not even trying. If you can’t be bothered, why should I (or anyone else) be ? Geesh … :evil:

skimask:
In other words…

Yup.

Very so sorry for that…, thanks you for your helping… :slight_smile: