Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 3 of 3

Thread: ADC writing to SD card strange issue - help please

  1. #1
    Junior Member Polly's Avatar
    Join Date
    Mar 2019
    Location
    Cardiff, UK
    Posts
    7

    ADC writing to SD card strange issue - help please

    Hello,

    I am writing a code that monitors a pin (which is attached to a signal generator) using the ADC i am using the ADC library written by pedvide and am using a Teensy 4.1. The code then writes the signal to a .csv file on an SD card.

    I need this to happen as fast as the Teensy can manage as I am trying to recording ultrasound upto about 350kHz. What I am seeing (and will include below) is that it doesn't seem to be using the 10bit range and is cutting the signal up into steps which are effect y-axis resolution. Each of these steps is sampled either 16 or 17 times and then the next point is sampled. On the lower frequency signals (10kHz I know this isn't ultrasound frequency I just needed to sanity check a few things) the sine wave is coming out fairly smooth but as I move faster (50kHz and 100kHz) it becomes more and more prone to the stepping effect (which makes sense).

    My question is why is this stepping occuring and what could I try to make the signals recorded smoother. Code is below, along with some pictures of the graphs I can create afterwards, I can't upload my result files (these are .csv, but I have changed the extension to .txt and .xls and neither will upload so I think that might be due to file size for some reason?

    Many thanks

    Polly

    My code:
    Code:
    #include <Wire.h>
    #include <TimeLib.h>
    #include <SPI.h>
    #include <SD.h>
    #include <ADC.h>
    #include <ADC_util.h>
    #include <ADC_Module.h>
    
    const int BuffSize = 110000;
    int value[BuffSize]; 
    
    ADC *adc = new ADC(); 
    
    void setup()
    {
        pinMode(16, INPUT_DISABLE); 
        pinMode (A2, INPUT); 
        
        Serial.begin(9600);
    
        adc->adc1->setReference(ADC_REFERENCE::REF_3V3);
        adc->adc1->enableInterrupts(adc1_isr);
        adc->adc1->setAveraging(1); // set number of averages
        adc->adc1->setResolution(10); // set bits of resolution
        adc->adc1->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
        adc->adc1->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED); // change the sampling speed
        adc->adc1->startContinuous(A2);
        
        !SD.begin(BUILTIN_SDCARD);
      
    }
    
    void loop()
    {
      for(int i=0; i<BuffSize;i++)
      {
      value[i] = (uint16_t)adc->adc1->analogReadContinuous();
      }
       
      //Open a file and write to it. 
      File dataFile = SD.open("File001.csv", FILE_WRITE); // *** name is in 8.3 format *** add date to this some how, perhaps make it automatic??
      if (dataFile)
      {
        for(int i=0; i<BuffSize;i++)
        {
        dataFile.print(micros()); // i added this after to check it was reading at different time points and not just writing the same time point over and over again
        dataFile.print(",");
        dataFile.println(value[i]);
        }
        dataFile.close(); //Data isn't actually written until we close the connection!
        }
       else{} 
       delay(0.1);
    }
    
    void adc1_isr(void) {
        adc->adc1->analogReadContinuous();
        }
    Click image for larger version. 

Name:	10kHzsinefirst10000samples.jpg 
Views:	12 
Size:	42.0 KB 
ID:	29348
    Click image for larger version. 

Name:	50kHzsinefirst10000samples.jpg 
Views:	6 
Size:	78.1 KB 
ID:	29349
    Click image for larger version. 

Name:	100kHzsinefirst10000samples.jpg 
Views:	9 
Size:	84.7 KB 
ID:	29350

  2. #2
    Senior Member
    Join Date
    Feb 2018
    Location
    Corvallis, OR
    Posts
    374
    I think your problem is that the foreground loop that is storing the ADC values is running much faster than the ADC is converting. analogReadContinuous is a very short inline function that simply returns the value in the ADC data register. When the ADC is converting continuously, it will take longer to read and convert the value than it does to simply read the result register in your foreground loop.

    You have two options:

    1. Don't bother with the interrupts and in your foreground loop wait for a new conversion to occur :
    Code:
    for(int i=0; i< BuffSize; i++){
    while( !adc->adc1->isComplete()){};   // wait until a new conversion is complete
    value[i] = idc->adc1->analogReadSingle() ;    // like analogReadContinuous, just reads the result register
    } // end of for loop
    2. Put the data collection into the background and have it collected in the interrupt handler. This is often done when you need to collect continuously in the background and write the results in the foreground. To get the foreground loop to write to SD as fast as you are collecting may require writing binary data records. I think there are some sample programs in the forum using that technique. Search for a thread "1MSPS on a T4"

    There's a lot of issues to consider if you want to collect 12-bit data at high rates. The "1 MSPS" thread covers many of them with a lot of sample code.

  3. #3
    Junior Member Polly's Avatar
    Join Date
    Mar 2019
    Location
    Cardiff, UK
    Posts
    7
    Hi, Thank you for your help! I am working through all the 1 MSPS thread at the moment. I will do a proper reply when I have it all working. Thank you so much I have been struggling with this for ages now. Polly

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •