Changeing the ADC Resolution / Speed

Hello everyone,

I'm currently trying to read the data from a Hamamatsu c12880ma microspectrometer. It works with the standart ADC speed of the arduino 101 however the resolution and of course the time it takes to read the 288 data points could be increased by increasing the sample rate and so the overall clock frequency for the spectrometer.
The c1000 and the curie datasheet both say that the adc is capable of doing 2.4Msamples/s so I would like to know how to archive that.
I figured out, that within the variant.h file the ADC prescaler is set to 1/32th so removing the prescaler gave me a samplerate of about 300kSample/s. Its quite an improvement, but still far of the 2.4mSample/s that the ADC should be capable of.
I also removed the bit shifting, to create a 10 bit analog value out of the actual 12 bit value to gain more speed.

From what i understood from the datasheet. there is a posebility to also set a prescaler to general SS-clock however i am not able to find that part. Also I cant find the ADC_RES register, which is named by the curie datasheet in order to lower the adc resolution.

If anyone could help me understanding the registers of the c1000 module I would be really thankfull.

Thanks in advance.

Hi nuclear213, I'm not sure offhand how to achieve this, but I can take a look. Could you share with me

  1. the code changes you made to increase you sampling speed (I assume you just changed ADC_CLOCK_RATIO in variant.h from 32 to 1, but please confirm your specific changes)

  2. The sketch you are using to test your sample rate (i.e. the sketch you used to determine 300k samples)

Hi,

yes thats what i did that but i also removed the mapping in the analogRead function :slight_smile: however i was quite supriesed that it only created a 10 times improvement instead a 32 times, what i would have guessed if i increase the clockrate of the adc.
Looking throught the example code intel system studio has for the c1000 controller i would assume, that one way of speeding it up would be actually using the sequencer to perform lets say 10 messurements at a time and then reading the fifo at once. So basically doing it the way they implemented it.

Regarding the Resolution im a bit confused. As far as i understand the intel code,the value that is written in the ADC_CONFIG_SETUP (0x0B) and so get written in the ADC_SET register with the variantAdcInit function should set the ADC Resolution. In their code intel says 0x05 = 6bit 0x07 = 8bit 0x09 = 10bit and 0X0B = 12bit.
However chaning that still doesnt matter for me as i get values > 63 when using 0x05. Im not quite sure whats going on there. Sadly I dont have a C1000 dev board so i cant test if their code is working as intended.

Thanks for your help

Edit:
The code I used to quickly test it:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {
  // put your main code here, to run repeatedly:
  int i;
  long stime;

  stime = micros();

  for (i=0;i < 10000;  i++)
    analogRead(A2);

  stime = micros() - stime;

  Serial.println(stime);
  Serial.println(analogRead(A3));
  delay(1000);
}

However I also tested it with the code to read out the spectrometer and also with that i noticed an about 10x increase. So I guess it should be quite accurate. It takes 3ms to read 288 datapoints with a lot of digitalWrites and delays.
The code to read it is:

void readSpectrometer(int inttime){

  int delayTime = 1; // delay time

  // Start clock cycle and set start pulse to signal start
  digitalWrite(SPEC_CLK, LOW);
  delayMicroseconds(delayTime);
  digitalWrite(SPEC_CLK, HIGH);
  delayMicroseconds(delayTime);
  digitalWrite(SPEC_CLK, LOW);
  digitalWrite(SPEC_ST, HIGH);
  delayMicroseconds(delayTime);

  //Sample for a period of time
  for(int i = 0; i < inttime; i++){

      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime); 
 
  }

  //Set SPEC_ST to low
  digitalWrite(SPEC_ST, LOW);

  //Sample for a period of time
  for(int i = 0; i < 85; i++){

      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime); 
      
  }

  //One more clock pulse before the actual read
  digitalWrite(SPEC_CLK, HIGH);
  delayMicroseconds(delayTime);
  digitalWrite(SPEC_CLK, LOW);
  delayMicroseconds(delayTime);

  //Read from SPEC_VIDEO
  for(int i = 0; i < SPEC_CHANNELS; i++){

      data[i] = analogRead(SPEC_VIDEO);
      
      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime);
        
  }


  for(int i = 0; i < 7; i++){
    
      digitalWrite(SPEC_CLK, HIGH);
      delayMicroseconds(delayTime);
      digitalWrite(SPEC_CLK, LOW);
      delayMicroseconds(delayTime);
    
  }

  digitalWrite(SPEC_CLK, HIGH);
  delayMicroseconds(delayTime);
  
}



void loop()
{
      int i;
      long stime;

      stime = micros();

      for (i=0; i < 1000; i++)
        readSpectrometer(150);

      stime = micros() - stime;

      Serial.println(stime);
      delay(100);
}