Need to increase the speed of the ADC

Hello, I'm new in the forum. I need to receive two analog signals of 100KHz and send it to the PC. It does not have to be real time but they must be reliable data. I looked at the datasheet and I have this code but it is not enough, is there any way to increase the sampling rate?

float value[230];
byte data[230];
int x,y,z;
void setup()
{
Serial.begin(9600); //

ADC->ADC_MR |= 0x80; // set free running mode on adc 7 and adc 6 (pin A0 and A1 - see Due Pinout Diagram thread)
ADC->ADC_CR=2;
ADC->ADC_CHER=0xC0; // this is (1<<7) | (1<<6) for adc 7 and adc 6

}

void loop(){
z=analogReadFast();
if (z>30);
{
for (y=0;y<100;y++){
datos[y]=analogReadFas();
}

for (x=0;x<100;x++){
valor[x]=datos[x];
valor[x]=valor[x]/255*5;
Serial.println(valor[x]);
}
}
}

int analogReadFast()
{
int a0;
for(int i=0;i<500000;i++){
while((ADC->ADC_ISR & 0x80)==0);// wait for two conversions (pin A0[7] and A1[6])
a0=ADC->ADC_CDR[7]; // read data on A0 pin
}
}
int analogReadFas()
{
int a1;
for(int i=0;i<500000;i++){
while((ADC->ADC_ISR & 0x40)==0);// wait for two conversions (pin A0[7] and A1[6])
a1=ADC->ADC_CDR[6]; // read data on A1 pin
}
}

Thanks for the help

Try a PDC DMA to increase speed. You have some examples here :

C/C++/Arduino use of Due(SAM3X8E), PDC, DMA etc. Seeking advice. - Arduino Due - Arduino Forum from #7

Yes, DMA would be helpful as the conversions would happen without CPU assistance. But, I think the true problem here is that the Arduino core doesn't set the ADC to a very fast clock rate. You can get 1M captures per second out of the ADC hardware if properly configured. Arduino doesn't do this by default so the conversion rate is slower. The biggest boost would occur by changing the ADC clock and related settings to speed up the conversion rate. However, most all of the DMA ADC examples will do this and DMA is nice so the above advice is still perfectly valid. I just figured I'd mention that the biggest thing to look at is the conversion speed.

Have a look at this page, towards the bottom

Thanks guys for the quick response!

The Code it's just what I needed, but I have a problem that could sound dumb, I'm using a wireless module to send data to the PC, using the serial port, but when I tried to use the code of stimmer, it doesn't work...

  • call of overloaded 'print(uint8_t*)' is ambiguous

That's the error.

I need to convert a uint_32 value to a uint_8. Can anybody help me??

Sorry if it's a dumb question.

If you must convert an integer of one size to another size you can use a C cast like this:

uint32_t myVariable = 0x2045;
print((uint8_t)myVariable);

That is, put (uint8_t) in front of where you're using the variable and it'll cast it down to the proper size.

Collin80:
If you must convert an integer of one size to another size you can use a C cast like this:

uint32_t myVariable = 0x2045;

print((uint8_t)myVariable);




That is, put (uint8_t) in front of where you're using the variable and it'll cast it down to the proper size.

I tried to do that way but doesn't work. The piece of code is:

ADC->ADC_RPR=(uint32_t)buf[0];
ADC->ADC_RNPR=(uint32_t)buf[1];
obufn=1

void loop(){
  while(obufn==bufn); // wait for buffer to be full
  Serial.print((uint8_t)buf[obufn]);
  obufn=(obufn+1)&3;    
}

And I get this error:

exit status 1
cast from 'uint16_t* {aka short unsigned int*}' to 'uint8_t {aka unsigned char}' loses precision [-fpermissive]

The original code is:

ADC->ADC_RPR=(uint32_t)buf[0];
ADC->ADC_RNPR=(uint32_t)buf[1];
obufn=1

void loop(){
  while(obufn==bufn); // wait for buffer to be full
  SerialUSB.write((uint8_t *)buf[obufn],512); 
  obufn=(obufn+1)&3;    
}

Oh, I see. Well, what is it you're trying to do? In this case, buf is an array that holds a set of pointers to memory locations that can be used by the DMA system to store ADC values. That's why the original code was written like it was. It cast the pointer stored at buf[obufn] to be a pointer to 8 bit values and then printed out 512 values from where the pointer points to. But, write sends data raw so if you're trying to look at the output in the serial monitor you'll see gibberish. Perhaps what you were looking to do was print the ADC values in a human readable format? If I remember correctly the stimmer code sets up DMA to take 256 readings from an analog port and stores it in the buffer. That's why there are 512 values, ADC is either 10 or 12 bit so you need two bytes per reading. So, if you wanted to print those out in a human readable format you could do this:

ADC->ADC_RPR=(uint32_t)buf[0];
ADC->ADC_RNPR=(uint32_t)buf[1];
obufn=1

void loop(){
  while(obufn==bufn); // wait for buffer to be full
  uint16_t *adcBuff = buf[obufn];
  for (int val = 0; val < 256; val++) {
     SerialUSB.println(adcBuff[val], HEX);
  }
  obufn=(obufn+1)&3;    
}

You'd get one value per line and in hexadecimal. If you don't like base 16 then remove the ", HEX" part.

1 Like

You're right Collin80, that was what happened, I realized that the problem was the array and came to the same conclusion than you, the code now it's working!

Thank you all for the help, you saved my week!

I'll be here more often, there's a lot to learn with Arduino.