Forum Rule: Always post complete source code & details to reproduce any issue!
Page 5 of 17 FirstFirst ... 3 4 5 6 7 15 ... LastLast
Results 101 to 125 of 420

Thread: ADC library update, now with support for Teensy 3.1

  1. #101
    Member
    Join Date
    Oct 2014
    Location
    World
    Posts
    31
    Quote Originally Posted by Pedvide View Post
    Update: Now it works with the Audio library:
    Teensy 3.0 is compatible, except if you try to use the Audio library ADC input (AudioInputAnalog), because there's only one ADC module so you can't use it for two things.
    Teensy 3.1 is compatible. If you want to use AudioInputAnalog and the ADC you have to use the ADC_1 module, the Audio library uses ADC_0. Any calls to functions that use ADC_0 will most likely crash the program. Note: make sure that you're using pins that ADC_1 can read (see pictures above)! Otherwise the library will try to use ADC_0 and it won't work!!
    Pedvide, this works fantastic! I numbers I get from my log scale light sensor are much more stable. Your library is certainly advanced but the more I read, I realized it is incredibly well documented! Thank you!

    I found this image helpful for those trying to figure out which pins are on ADC0, ADC1, or both!
    Click image for larger version. 

Name:	Teensy3_1_AnalogCard.png 
Views:	1685 
Size:	539.2 KB 
ID:	2881
    I have a jumper to cut and solder to change my mic pin, but this edit gets my two earlier prototypes running with ADC+Audio libraries!

    Also, I went ahead and cleaned up the example code below. It's based on PRJC's FFT example but configured for taking audio from a mic without the Audio Board and taking an analog reading from ADC1 which currently isn't used by InputAudioAnalog. New Users: currently AnalogReference(INTERNAL) is currently hard coded into the library, depending on you wiring/mic you may need to edit the library. See: https://github.com/PaulStoffregen/Audio/issues/89
    Important note from Paul on the topic:
    Quote Originally Posted by PaulStoffregen View Post
    I had originally intended to include an adc1.analogReference() function, like the DAC object has. Somehow, this never happened. It'll come in some future version. Pull requests are welcome.... (hint, hint)

    However, changing the reference to 3.3V will reduce the signal amplitude by 3. For hardware where the signal is already very low, you might be better off using the recommended circuit. Those 2 extra capacitors and 4 resistors will buy your 3X the signal gain.
    Code:
    // FFT Test for Analog Mic
    //
    // Use PRJC's Audio library to compute audio spectrum analysis 
    // from an analog mic input on ADC0 while taking an analog read 
    // sample from a pin on ADC1 using Pedvide's ADC library. 
    // Download the latest copy at:
    // https://github.com/pedvide/ADC
    //
    // Compute a 1024 point Fast Fourier Transform (spectrum analysis)
    // on audio connected to the Left Line-In pin.  By changing code,
    // a synthetic sine wave can be input instead.
    //
    // The first 40 (of 512) frequency analysis bins are printed to
    // the Arduino Serial Monitor.  Viewing the raw data can help you
    // understand how the FFT works and what results to expect when
    // using the data to control LEDs, motors, or other fun things!
    //
    // This example code is in the public domain. 
    
    
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    
    #include <ADC.h>
    
    // CREATE THE ADC OBJECT FIRST, BEFORE ALL AUDIO STUFF!!
    ADC *adc = new ADC(); // adc object
    const int readPin = 30; // ADC1, Choose a pin the can be accessed by the ADC *NOT* being used to stream audio.
                            // Currently this must be a pin on ADC1, but has been suggested as a fix for the audio library.
    
    // Create the Audio components.  These should be created in the
    // order data flows, inputs/sources -> processing -> outputs
    // Using adafruit mic-amp, edit library to turn-off internal voltage reference in 
    // inputAnalog.cpp 
    
    AudioInputAnalog       analogAudioIn(15); //Pin 15, mic pin, currently must be on ADC0
    AudioSynthWaveformSine sinewave;
    AudioAnalyzeFFT1024    myFFT;
    
    
    
    // Connect either the live input or synthesized sine wave
    AudioConnection patchCord1(analogAudioIn, 0, myFFT, 0);
    //AudioConnection patchCord1(sinewave, 0, myFFT, 0);
    
    
    
    
    void setup() {
      // Audio connections require memory to work.  For more
      // detailed information, see the MemoryAndCpuUsage example
      AudioMemory(12);
    
    
    
      // Configure the window algorithm to use
      //myFFT.windowFunction(AudioWindowHanning1024);
      myFFT.windowFunction(NULL);
    
      // Create a synthetic sine wave, for testing
      // To use this, edit the connections above
      sinewave.amplitude(0.8);
      sinewave.frequency(1034.007);
    
    
      adc->setAveraging(8, ADC_1); // set number of averages
      adc->setResolution(12, ADC_1); // set bits of resolution
      adc->setConversionSpeed(ADC_VERY_LOW_SPEED, ADC_1); // change the conversion speed
      adc->setSamplingSpeed(ADC_VERY_LOW_SPEED, ADC_1); // change the sampling speed
    
    }
    
    int value = 0;
    
    void loop() {
      float n;
      int i;
    
      value = adc->analogRead(readPin, ADC_1); // read a new value, will return ADC_ERROR_VALUE if the comparison is false.
    
      if (myFFT.available()) {
        // each time new FFT data is available
        // print it all to the Arduino Serial Monitor
        //Serial.print("T: "); //Testing touchRead
        //Serial.print(touchRead(0));
        Serial.print("Pin: ");
        Serial.print(readPin);
        Serial.print(" = ");
        Serial.print(value*3.3/adc->getMaxValue(ADC_1), DEC); //assuming 3.3v reference voltage
        Serial.print("v   FFT: ");
        for (i=0; i<40; i++) {
          n = myFFT.read(i);
          if (n >= 0.008) {
            Serial.print(n);
            Serial.print(" ");
          } 
          else {
            Serial.print("  -  "); // don't print "0.00"
          }
        }
        Serial.print("\n"); 
      }
    }
    I've learned a lot from this issue! Thanks to everyone who helped!

  2. #102
    Member
    Join Date
    Mar 2013
    Location
    Austin, TX
    Posts
    92
    I'm having issues with ringBufferDMA
    It only seems to be recording to the first 4 values.

    Here's the output I get after sending "sccccccccp" I have a pot connected to the input pin around 3300.
    Code:
    Start DMA
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Conversion: 
    ADC0_ISR
    DMA_CH2_ISR
    Buffer: Address, Value
    1FFF9388, 3308
    1FFF938A, 3306
    1FFF938C, 3310
    1FFF938E, 3311
    1FFF9390, 10236
    1FFF9392, -30318
    1FFF9394, -18379
    1FFF9396, -32235
    Subsequent reads only write over the first 4. That data only changes when I unplug and reconnect the Teensy.
    I've tried it with the interrupt off with the same results.
    I'm using Arduino 1.0.6 and Teesny 1.20 with a 3.1.

    Thanks!
    Last edited by john-mike; 12-09-2014 at 06:23 PM.

  3. #103
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    I'll have a look at it. The DMA part will benefit from all the additions to the Teensy core.
    What's happening is that the buffer should start at an address ending in 0, but it's not. When it reaches the address 1FFF938E it wraps around to 1FFF9380 (probably).

  4. #104
    Quote Originally Posted by Pedvide View Post
    I'll have a look at it. The DMA part will benefit from all the additions to the Teensy core.
    What's happening is that the buffer should start at an address ending in 0, but it's not. When it reaches the address 1FFF938E it wraps around to 1FFF9380 (probably).
    I've been looking into this as I was suffering from this as well. It did seem to come and go, but I did find a few weird things in the library code:
    1. Line 161 of RingBufferDMA.cpp
    return (p + 1)&(2*b_size-1);
    I believe that that 2 should not be there, i.e the line should read
    return (p + 1)&(b_size-1);

    2. When that is fixed you can drop the extra test against b_start at line 154 so that it can read
    int result = elems[b_start];

    3. I've been trying to play with the value of DMA_BUFFER_SIZE to increase it to at least 64 which I need to try and improve Serial.write to increase sampling rate in my code (currently limited to 67KHz). Seems that it does not work with any value about 8. I don't know enough arduino low level code to figure out what is wrong, only hint is in the comment on line 92
    src and dst data is 16 bit (2 bytes), buffer size 2^^4 bytes = 8 values

    Is there a way to increase the buffer size?

    Thanks

  5. #105
    Senior Member
    Join Date
    Mar 2013
    Posts
    651
    Having some fun with the library. Im reading 6 different analog pins in sequence using synchronized reads and repeating 16 times.
    Averaging 1 sync read every 11us or 5.5uS per pin @ 48MHz and 8.6us or 4.3uS per pin @ 72MHz.

    Here is the code, im sure its hard on the eyes for you coding pros...


    Code:
    #include <ADC.h>
    
    const int readPin = A0;    //Throttle
    const int readPin2 = A18;  //Current
    const int readPin3 = A1;   //BusV
    const int readPin4 = A19;  //BattV
    const int readPin5 = A2;   //MotorTemp
    const int readPin6 = A20;  //HS-Temp
    
    ADC *adc = new ADC(); // adc object
    
    
    void setup() {
    
        pinMode(LED_BUILTIN, OUTPUT);
        pinMode(readPin, INPUT);
        pinMode(readPin2, INPUT);
        pinMode(readPin3, INPUT);
        pinMode(readPin4, INPUT);
        pinMode(readPin5, INPUT);
        pinMode(readPin6, INPUT);
    
    
        Serial.begin(9600);
    
        ///// ADC0 ////
        //adc->setReference(ADC_REF_INTERNAL, ADC_0); change all 3.3 to 1.2 if you change the reference
    
        adc->setAveraging(1); // set number of averages
        adc->setResolution(12); // set bits of resolution
    
        // it can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED_16BITS, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
        // see the documentation for more information
        adc->setConversionSpeed(ADC_HIGH_SPEED); // change the conversion speed
        // it can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
        adc->setSamplingSpeed(ADC_HIGH_SPEED); // change the sampling speed
    
        // always call the compare functions after changing the resolution!
        //adc->enableCompare(1.0/3.3*adc->getMaxValue(ADC_0), 0, ADC_0); // measurement will be ready if value < 1.0V
        //adc->enableCompareRange(1.0*adc->getMaxValue(ADC_0)/3.3, 2.0*adc->getMaxValue(ADC_0)/3.3, 0, 1, ADC_0); // ready if value lies out of [1.0,2.0] V
    
        ////// ADC1 /////
        adc->setAveraging(1, ADC_1); // set number of averages
        adc->setResolution(12, ADC_1); // set bits of resolution
        adc->setConversionSpeed(ADC_HIGH_SPEED, ADC_1); // change the conversion speed
        adc->setSamplingSpeed(ADC_HIGH_SPEED, ADC_1); // change the sampling speed
    
        // always call the compare functions after changing the resolution!
        //adc->enableCompare(1.0/3.3*adc->getMaxValue(ADC_1), 0, ADC_1); // measurement will be ready if value < 1.0V
        //adc->enableCompareRange(1.0*adc->getMaxValue(ADC_1)/3.3, 2.0*adc->getMaxValue(ADC_1)/3.3, 0, 1, ADC_1); // ready if value lies out of [1.0,2.0] V
    
    
        delay(500);
        Serial.println("end setup");
    }
    
    int value[16] = {0};
    int value2[16] = {0};
    int value3[16] = {0};
    int value4[16] = {0};
    int value5[16] = {0};
    int value6[16] = {0};
    int testtime;
    
    ADC::Sync_result result;
    
    void loop() {
      
    int i;
    
    elapsedMicros sinceStart; // start the clock
    
    for (i = 0; i < 16; i++) {
        result = adc->analogSynchronizedRead(readPin, readPin2);
        value[i] = result.result_adc0;
        value2[i] = result.result_adc1;
        result = adc->analogSynchronizedRead(readPin3, readPin4);
        value3[i] = result.result_adc0;
        value4[i] = result.result_adc1;
        result = adc->analogSynchronizedRead(readPin5, readPin6);
        value5[i] = result.result_adc0;
        value6[i] = result.result_adc1;
    
    }
    
    testtime = sinceStart;   //how long it took to read all 6 pins 16 times.
    Serial.print("Full read time was ");
    Serial.print(testtime);
    Serial.println(" us");
    
    //First ADC array                        
        Serial.print("Pin: ");   //Copy and paste hell from here on out...
        Serial.print(readPin);
        Serial.print(", value ADC0: ");
    
    for (i = 0; i < 16; i++) {
        Serial.print(value[i]*3.3/adc->getMaxValue(ADC_0), DEC);
            Serial.print(" ");  
    }
    
    //Second ADC array
        Serial.println(" ");
        Serial.print("Pin: ");   //Copy and paste hell from here on out...
        Serial.print(readPin2);
        Serial.print(", value ADC1: ");
    
    for (i = 0; i < 16; i++) {
        Serial.print(value2[i]*3.3/adc->getMaxValue(ADC_1), DEC);  
            Serial.print(" ");
    }
    
    //Third ADC array
        Serial.println(" ");
        Serial.print("Pin: ");   //Copy and paste hell from here on out...
        Serial.print(readPin3);
        Serial.print(", value ADC0: ");
    
    for (i = 0; i < 16; i++) {
        Serial.print(value3[i]*3.3/adc->getMaxValue(ADC_0), DEC);
            Serial.print(" ");  
    }
    
    //Forth ADC array
        Serial.println(" ");
        Serial.print("Pin: ");   //Copy and paste hell from here on out...
        Serial.print(readPin4);
        Serial.print(", value ADC1: ");
    
    for (i = 0; i < 16; i++) {
        Serial.print(value4[i]*3.3/adc->getMaxValue(ADC_1), DEC);
          Serial.print(" ");  
    }
    
    //Fifth ADC array
        Serial.println(" ");
        Serial.print("Pin: ");   //Copy and paste hell from here on out...
        Serial.print(readPin5);
        Serial.print(", value ADC0: ");
    
    for (i = 0; i < 16; i++) {
        Serial.print(value5[i]*3.3/adc->getMaxValue(ADC_0), DEC);
          Serial.print(" ");  
    }
    
    //Sixth ADC array
        Serial.println(" ");
        Serial.print("Pin: ");   //Copy and paste hell from here on out...
        Serial.print(readPin6);
        Serial.print(", value ADC1: ");
    
    for (i = 0; i < 16; i++) {
        Serial.print(value6[i]*3.3/adc->getMaxValue(ADC_1), DEC);
          Serial.print(" ");  
    }
    
    
      delay(1000);
    }
    And a few snips from my serial monitor.
    DMM values are
    Pin 14: 3.072V
    Pin 29: 2.047V
    Pin 15: 1.699V
    Pin 30: 2.349V
    Pin 16: 0.783V
    Pin 31: 2.683V

    Code:
    6 channels in arrays @ 48MHz
    Full read time was 522 us
    Pin: 14, value ADC0: 3.0775824 3.0759706 3.0759706 3.0775824 3.0767765 3.0767765 3.0767765 3.0767765 3.0759706 3.1041758 3.0630769 3.0759706 3.0711355 3.0743589 3.0767765 3.0695238  
    Pin: 29, value ADC1: 2.0541391 2.0541391 2.0541391 2.0557509 2.0565567 2.0549450 2.0549450 2.0557509 2.0541391 2.0533333 2.0581684 2.0557509 2.0541391 2.0613919 2.0557509 2.0533333  
    Pin: 15, value ADC0: 1.7027838 1.7060073 1.7060073 1.7052014 1.6979487 1.7052014 1.7060073 1.7043956 1.7060073 1.7060073 1.7060073 1.7084249 1.7060073 1.7043956 1.7060073 1.7060073  
    Pin: 30, value ADC1: 2.3539194 2.3555311 2.3555311 2.3547252 2.3563369 2.3434432 2.3539194 2.3547252 2.3563369 2.3555311 2.3547252 2.3563369 2.3555311 2.3547252 2.3571428 2.3555311  
    Pin: 16, value ADC0: 0.7736263 0.7913553 0.7744322 0.7913553 0.7905494 0.7752380 0.7736263 0.7945787 0.7744322 0.7905494 0.7800732 0.7921611 0.7897435 0.7736263 0.7921611 0.7752380  
    Pin: 31, value ADC1: 2.6883516 2.6883516 2.6891575 2.6891575 2.6891575 2.6883516 2.6891575 2.6956043 2.6859340 2.6875457 2.6907692 2.6988278 2.6907692 2.6899633 2.6915750 2.6891575
    Code:
    6 channels in arrays @ 72MHz
    Full read time was 411 us
    Pin: 14, value ADC0: 3.0743589 3.0759706 3.0783882 3.0767765 3.0783882 3.0783882 3.0783882 3.0759706 3.0783882 3.0783882 3.0767765 3.0759706 3.0824175 3.0791941 3.0783882 3.0735531  
    Pin: 29, value ADC1: 2.0525274 2.0541391 2.0549450 2.0541391 2.0533333 2.0533333 2.0549450 2.0557509 2.0541391 2.0549450 2.0549450 2.0557509 2.0533333 2.0493040 2.0509157 2.0589743  
    Pin: 15, value ADC0: 1.7035897 1.7052014 1.7060073 1.7068131 1.7068131 1.7084249 1.7076190 1.7068131 1.7068131 1.7076190 1.7068131 1.7132600 1.7068131 1.7084249 1.7011721 1.7172893  
    Pin: 30, value ADC1: 2.3539194 2.3555311 2.3571428 2.3571428 2.3571428 2.3579487 2.3579487 2.3579487 2.3579487 2.3571428 2.3571428 2.3619780 2.3531135 2.3660073 2.3595604 2.3571428  
    Pin: 16, value ADC0: 0.7832967 0.7849084 0.7849084 0.7849084 0.7849084 0.7857142 0.7849084 0.7849084 0.7849084 0.7849084 0.7849084 0.7816849 0.7760439 0.7816849 0.7784615 0.7841025  
    Pin: 31, value ADC1: 2.6867399 2.6883516 2.6899633 2.6899633 2.6899633 2.6907692 2.6899633 2.6907692 2.6907692 2.6915750 2.6907692 2.6915750 2.6915750 2.6778754 2.6867399 2.6899633
    I may make a none synchronized version to see if its slower or faster.
    Last edited by Donziboy2; 01-10-2015 at 11:56 PM.

  6. #106
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    laughingrice,
    thanks for the suggestions, now I'm working hard on USB Host mode, so I'm not sure when I'll be able to test this.
    About changing the buffer size, you have to change the DMA buffer size too! In line 90 change DMA_TCD_ATTR_DMOD(4); to other sizes. The implementation of the circular buffer only works with sizes that are powers of 2.

    Donziboy2,
    Your code looks good! Something else you can try is to do the 16 reads on the same pair of pins consecutively, then an other 16 reads of the other 2 pins, etc. See if there's a difference in speed and/or accuracy.

  7. #107
    Senior Member
    Join Date
    Mar 2013
    Posts
    651
    Quote Originally Posted by Pedvide View Post
    Donziboy2,
    Your code looks good! Something else you can try is to do the 16 reads on the same pair of pins consecutively, then an other 16 reads of the other 2 pins, etc. See if there's a difference in speed and/or accuracy.
    Thanks, the reason I ran them that way is I needed to see how long it takes to read a pair then switch to the next set. I want to squeeze all the speed I can get from them. I plan to sample all 6 and then average the samples over time. Im slowly working on a motor controller for a Go Cart and I want to sample the 6 apins + some dpins at 4Ksps or greater. I have been bouncing between testing small pieces of code and cramming all the components on 3 small boards that are 96.5x116.8mm that will be stacked on top of each other. All the analogs will be connected to Op-Amps so I should be able to keep the noise down and I will be averaging a good number of samples.

    I have plans to run a touch screen also but it may get interesting since I think the only way to do it is send the data to another teensy and do the screen on it plus I would like to log the data also so if I run into issues I can trouble shoot it.

    Hardware wise I have it mostly down, its the code that I have been neglecting

  8. #108
    Senior Member
    Join Date
    Mar 2013
    Posts
    651
    Oddly enough increasing the clock rate to 96MHz actually increased the total read time from 411us at 72MHz to 425us....

    Another odd thing I noticed that is probably more to do with the IDE is that I decided to remove the 3.3 value from "Serial.print(value3[i]*3.3/adc->getMaxValue(ADC_0), DEC);" since I used it in multiple places and just use a single float variable which would make it easier to tune later instead of having to change it several times. When I changed my above code it ended up using close to a thousand bytes more then the original code.
    Last edited by Donziboy2; 01-12-2015 at 01:22 AM.

  9. #109
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,248

    Cool

    I suspect when you moved the 3.3 value to a variable, you did not use the const keyword in declaring it. If you used const the compiler could do constant folding on the operation. This assumes you are coding in C++ (i.e. in the .ino/.pde file or in .cpp library files). If you are coding a library function in pure C, the rules for const are different, and the compiler has to treat it like a variable (but one it could put in read-only memory).

  10. #110
    Senior Member
    Join Date
    Dec 2014
    Posts
    306
    Quote Originally Posted by Donziboy2 View Post
    Oddly enough increasing the clock rate to 96MHz actually increased the total read time from 411us at 72MHz to 425us....

    Another odd thing I noticed that is probably more to do with the IDE is that I decided to remove the 3.3 value from "Serial.print(value3[i]*3.3/adc->getMaxValue(ADC_0), DEC);" since I used it in multiple places and just use a single float variable which would make it easier to tune later instead of having to change it several times. When I changed my above code it ended up using close to a thousand bytes more then the original code.

    Because the teensy doesn't have an FPU, any work with floats is significantly slower than regular integer math. I also believe that using the float data types adds an additional file to the compilation process in order for the teensy to deal with floats, which would explain your increased compiled program size.


    Edit: having said all that, you were using a decimal in your original code anyway so I might be talking rubbish.
    Last edited by Cosford; 01-12-2015 at 08:36 AM.

  11. #111
    Senior Member
    Join Date
    Mar 2013
    Posts
    651
    @MichaelMeissner

    I used a const and I placed it at the top of the code along with the pin constants I used.
    As for using C++ I have a hard enough time with normal C


    @Cosford

    The reason I tried it was to get rid of the 6 times I repeated 3.3 in the code and have one value I could change once I know what my actual 3.3V power rail is at.

  12. #112
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    You can try using a #define

  13. #113
    Senior Member
    Join Date
    Mar 2013
    Posts
    651
    Pedvide, what specifically do you mean when you say the Library is Interrupt friendly?

  14. #114
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    With that I mean two things:

    All registers bits are changed using their bit-band addresses, so the modify instructions are atomic. This means that if you change a bit 0 in register regA (example) inside an interrupt, and in the main loop you change bit1 in regA, you can be sure that the bits will have the values you wanted.
    If the library didn't use atomic access then the loop code would read the value of regA, change bit1, and write the old regA+the modified bit. The problem is that if the interrupt happens just after reading regA, but before writing it again, and the interrupt code changes bit 1, when the interrupt returns and the loop code executes it will write an old version of regA, thus reverting the changes of the interrupt.

    The second point is that when you start a measurement that isn't continuous, the function checks whether the ADC is already running, if so, it stores the settings, does the reading, and then restores the ADC so it continues doing the measurement.
    For example, if you have a continuous measurement in pin1 but from time to time you want to measure the voltage of pin2, you can just simply call analogRead(pin2) (from normal code or an interrupt). It will "pause" the continuous measurement, return the value of pin2 and restore the ADC so it keeps measuring pin1.

  15. #115
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,668
    Anybody have the Windows base beta 1.6 ready to run that can give this compile a try - Paul's suspecting there may be a Windows anomaly.
    WARNING: library Audio claims to run on [sam] architecture(s) and may be incompatible with your current board which runs on [avr] architecture(s).
    For my Teensy 3.1 I'm trying to use this above code from Message #101 above on Win7 and Win8 with the current 1.6 beta and my systems are coming up AVR and not SAM and it won't compile using the Arduino libs the IDE is trying.

    - which would delay important work - anyone reading this compiling it with the Beta on a Windows system? I've done what I can to disprove user error, I also can't get the included "C:\Users\Tim\Documents\Arduino\hardware\teensy\av r\libraries\Audio\examples\Analysis\FFT\FFT.ino" example to work. Closest I get is when I delete the true Arduino AVR :: "C:\Users\Tim\Documents\Arduino\libraries\Audi o" - which is just grasping debuggery.

  16. #116
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,668
    Paul gave this a try and it worked - Looks like I get to clean install 3 machines.

    UPDATE: Above post #101 still failing on my clean 1.6 ZIP file copy.
    Last edited by defragster; 02-27-2015 at 07:40 PM.

  17. #117
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    I will test the library with Arduino 1.6 and also the Teensy LC in the following weeks.

  18. #118
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,668
    Code from the above post #101 still results in my getting this error. If anyone else [1.6 and TeensyDuino Beta-6] [with a WINDOWS system] could confirm.:
    T_ADCLibUpd_101_25532.ino:26:17: fatal error: ADC.h: No such file or directory
    compilation terminated.
    Error compiling.
    Last edited by defragster; 02-27-2015 at 11:55 PM.

  19. #119
    Senior Member
    Join Date
    Oct 2012
    Location
    Portland OR
    Posts
    676
    The ADC library at https://github.com/pedvide/ADC works with Arduino 1.0.6 / Teensyduino 1.21-beta6 for Teensy 3.0, but does not compile for Teensy LC, the error is:

    Code:
    C:\Program Files (x86)\Arduino\libraries\ADC-master\ADC.cpp: In function 'void dma_isr_0()':
    C:\Program Files (x86)\Arduino\libraries\ADC-master\ADC.cpp:1165:5: error: 'DMA_CINT' was not declared in this scope
         DMA_CINT = ADC::dma_Ch0;
         ^
    Last edited by JBeale; 02-27-2015 at 07:36 PM.

  20. #120
    Senior Member
    Join Date
    Mar 2013
    Posts
    651
    Quote Originally Posted by Pedvide View Post
    With that I mean two things:

    All registers bits are changed using their bit-band addresses, so the modify instructions are atomic. This means that if you change a bit 0 in register regA (example) inside an interrupt, and in the main loop you change bit1 in regA, you can be sure that the bits will have the values you wanted.
    If the library didn't use atomic access then the loop code would read the value of regA, change bit1, and write the old regA+the modified bit. The problem is that if the interrupt happens just after reading regA, but before writing it again, and the interrupt code changes bit 1, when the interrupt returns and the loop code executes it will write an old version of regA, thus reverting the changes of the interrupt.

    The second point is that when you start a measurement that isn't continuous, the function checks whether the ADC is already running, if so, it stores the settings, does the reading, and then restores the ADC so it continues doing the measurement.
    For example, if you have a continuous measurement in pin1 but from time to time you want to measure the voltage of pin2, you can just simply call analogRead(pin2) (from normal code or an interrupt). It will "pause" the continuous measurement, return the value of pin2 and restore the ADC so it keeps measuring pin1.
    Thank you

  21. #121
    Is there a method to get the ADC sampling speed for a given configuration (F_CPU + sampling + conversion + resolution + averaging) that doesn't involve reverse engineering the bitfields from the ADC module and datasheet ? I'm putting the above values in an array so I can cycle through speeds from slow to fast (a unidimensional level of abstraction over the multiple settings if you will) and it would be nice to be able to know the target speed.

  22. #122
    Junior Member
    Join Date
    Mar 2015
    Posts
    5
    I am having a bit of a hard time understanding how fast the sampling speed can go. Maybe someone could help me out here.
    ADC_HIGH_SPEED is guaranteed to be the highest possible speed within specs for resolutions less than 16 bits (lower or eq than 18 MHz).
    So in this setting the Teensy 3.1 can go up tp 18MHz?
    Well why does the AnalogContinuousRead example then say:
    At 96 Mhz (bus at 48 MHz), 632 KHz is the fastest we can do within the specs, and only if the sample's impedance is low enough.
    I don't get it.

  23. #123
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,546
    Well, there's 2 parts to that statement.

    Part 1: "632 KHz is the fastest we can do within the specs"

    This means 632000 samples per second is the maximum speed. That seems pretty simple, doesn't it?

    Maybe you're seeing mention of other frequencies like 18 MHz. Those are internal settings. Perhaps a more beginner oriented explanation would omit those finer details of stuff going on internally.

    Ultimately, the sample answer is 632 kHz is the maximum speed. You may wish for it to be faster, but wishful thinking will not make it so. Misunderstanding related specs for internal timing will not change the speed.


    Part 2: "only if the sample's impedance is low enough"

    Just because Teensy measures the voltage 632000 times per second doesn't necessarily mean your signal is that good.

    Even though 300 kHz of signal bandwitdh (Nyquist sampling theory says your signal can be up to half the sample rate... any more causes terrible problems called "aliasing") doesn't seem like a large number compared to digital clock speeds of modern processors, in fact delivering a 300 kHz bandwidth analog signal isn't always easy. One of the big challenges involves the strength (or source impedance) of your signal. If your signals goes through resistors or inductors, or if the source of your signal just isn't very strong due to the type of sensor, you'll almost certainly need a high quality amplifier to deliver a strong (low impedance) signal to Teensy.

    Some of the optional settings allow for weaker (higher impedance) signals, but at reduced speed. Such settings could be really useful for other people, who might prefer slower speed instead of the cost and complexity of adding a special amplifier circuit. But if you want to run as fast as possible, the highest speed settings only work with very strong signals.

  24. #124
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    Measuring a voltage involves two steps: sampling and conversing.
    Sampling basically means charging a capacitor inside de ADC so that it has the same voltage as the one you want to measure. The longer you wait, the more similar is the capacitor's voltage to the real voltage.
    The conversion then has to find the digital number that approximates the analog voltage on the capacitor, again, the longer you wait, the more precise is that value.

    The sampling speed is measured in how many ADC clock cycles it takes for the sampling. There's a minimum sampling time (I don't know the exact value) that is selected with ADC_VERY_HIGH_SPEED, the other settings will increase the sampling time up to 24 cycles for ADC_VERY_LOW_SPEED.
    The conversion step uses many ADC cycles to obtain the value, this number depends on the resolution and averaging. The conversing speed changes the ADC clock speed (and that depends on the bus clock speed). For 96 MHz main clock (48 MHz bus clock) you can select 3, 6, 12 and 24 MHz.
    In any case the ADC specs say you shouldn't operate the ADC slower than 1 MHz or faster than 18 MHz, for 16 bits those limits are 2 MHz and 12 MHz, respectively.

    Combining all those factors we find out that the maximum conversion speed at 8 bits of resolution and maximum sampling speed is 632 kHz (see the end of this example for more speeds).
    If you are willing to use speeds that are out of specs (which I don't know if they can damage the ADC module or only decrease the actual resolution) you can get 1262 kHz.

    I hope this answers your question.

    edit: I see Paul also answered your question. As he says, the 18 MHz is an internal setting, the ADC needs many cycles to convert the value, so after all is taken into account you are left with 632 kHz.
    Last edited by Pedvide; 03-13-2015 at 10:26 AM.

  25. #125
    Junior Member
    Join Date
    Mar 2015
    Posts
    5
    Thank you for the great answers!!
    I understand now, I was just wondering because of this instructable for an oscilloscope using the Arduino UNO: http://www.instructables.com/id/Giri...cope/?ALLSTEPS
    The author claims that "...we can see that for 8-bits precision the frequency could go up to 1.5 MHz, good!"
    So I thought, if the UNO has a 16MHz clock and can convert in a speed up to 1,5MHz, the Teensy 3.1 with (overclocked) 96MHz might be able to do more.

Posting Permissions

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