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

Thread: ADC Library - faster conversions

  1. #1
    Member
    Join Date
    Apr 2020
    Location
    HyŤres, France
    Posts
    25

    ADC Library - faster conversions

    Hi all
    I'm working on a music midi project using Teensy 3.2. I have 22 sensors, 16 of which are monitored by pin A1 using a 16 channel Multiplexer and the remaining sensors using the ADC channels on the Teensy board. Everything works, but it seems that the sampling is just not quick enough to measure all the sensors quick enough for the speed of my fingers. For example 1/32 note at tempo 180, there are missed notes. I've been looking at Pedvides ADC Library and this seems to be the key, as I am currently just using analogRead... However, there doesn't seem to be much information on how to use the library. Can anyone offer me a road map on how to use this library. Also, I have attached a snippet from my code and I would be most grateful if any of you more experienced programmers could offer me some support.

    Thank you in advance.
    Ged.


    Code:
    //---------------------------------------------------------------------------//
    
    void readSwitches() {    
    
        //First read value of all Key Sensors
        digitalWrite(4, LOW);   //S0    //Sample from MUX 1
        digitalWrite(3, LOW);   //S1              //0000
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, LOW);   //S3
        U11 = analogRead(A1);   //Samples through MUX_I0 channel
    
        digitalWrite(4, HIGH);   //S0              //0001
        digitalWrite(3, LOW);   //S1 
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, LOW);   //S3
        U10 = analogRead(A1);   //Samples through MUX_I1 channel
    
        digitalWrite(4, LOW);   //S0              //0010
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, LOW);   //S3
        U8 = analogRead(A1);   //Samples through MUX_I2 channel
    
        digitalWrite(4, HIGH);   //S0              //0011
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, LOW);   //S3
        U9 = analogRead(A1);   //Samples through MUX_I3 channel
    
        digitalWrite(4, LOW);   //S0              //0100
        digitalWrite(3, LOW);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, LOW);   //S3
        U4 = analogRead(A1);   //Samples through MUX_I4 channel
    
        digitalWrite(4, HIGH);   //S0              //0101
        digitalWrite(3, LOW);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, LOW);   //S3
        U5 = analogRead(A1);   //Samples through MUX_I5 channel
    
        digitalWrite(4, LOW);   //S0              //0110
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, LOW);   //S3
        U12 = analogRead(A1);    //Samples through MUX_I6 channel    
    
        digitalWrite(4, HIGH);   //S0              //0111
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, LOW);   //S3
        U13 = analogRead(A1);   //Samples through MUX_I7 channel
    
        digitalWrite(4, LOW);   //S0              //1000
        digitalWrite(3, LOW);   //S1 
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, HIGH);   //S3
        U3 = analogRead(A1);    //Samples through MUX_I8 channel
    
        digitalWrite(4, HIGH);   //S0              //1001
        digitalWrite(3, LOW);   //S1 
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, HIGH);   //S3
        U2 = analogRead(A1);   //Samples through MUX_I9 channel
    
        digitalWrite(4, LOW);   //S0              //1010
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, HIGH);   //S3
        U1 = analogRead(A1);   //Samples through MUX_I10 channel
    
        digitalWrite(4, HIGH);   //S0              //1011
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, LOW);   //S2
        digitalWrite(0, HIGH);   //S3
        U14 = analogRead(A1);   //Samples through MUX_I11 channel
    
        digitalWrite(4, LOW);   //S0              //1100
        digitalWrite(3, LOW);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, HIGH);   //S3
        U16 = analogRead(A1);    //Samples through MUX_I12 channel 
    
        digitalWrite(4, HIGH);   //S0              //1101
        digitalWrite(3, LOW);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, HIGH);   //S3
        U15 = analogRead(A1);   //Samples through MUX_I13 channel
    
        digitalWrite(4, LOW);   //S0              //1110
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, HIGH);   //S3
        U7 = analogRead(A1);   //Samples through MUX_I14 channel
    
        digitalWrite(4, HIGH);   //S0              //1111
        digitalWrite(3, HIGH);   //S1 
        digitalWrite(1, HIGH);   //S2
        digitalWrite(0, HIGH);   //S3
        U6 = analogRead(A1);   //Samples through MUX_I15 channel
    
        U17 = analogRead(A2);
        U18 = analogRead(A3);
        U19 = analogRead(A4);
    
        U20 = analogRead(A5);
        U21 = analogRead(A6);
        U22 = analogRead(A7);
    Last edited by GiGiUK; 07-03-2021 at 06:38 PM.

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,701
    Using digitalWriteFast() instead of digitalWrite() would get the output bits set faster.

    Seems there should be some delay for the Mux to settle new output before reading after changing the digitalWrite()'s.

    How many bits are needed - was Resolution set?

    How many Avg Samples are needed - was Average set?

    Code:
    analogReadResolution(12);  // set #bits 8 to 16
    analogReadAveraging(1); // 1,4,8,16,32

  3. #3
    Member
    Join Date
    Apr 2020
    Location
    HyŤres, France
    Posts
    25
    Hi defragster
    No Resolution has been set, but I think I could get away with eight bit. I'm not sure about the average samples, I think one sample would be enough as the ADC is just monitoring a sensor that provides an analog output.

    What would I think would help is:
    1. having both ADC0 and ADC1 sampling at the same time
    2. DMA transfer
    3. a way of testing how fast my code is running

    but, I dont know how to do that, any thoughts?

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,701
    Given the MUX presents a single value - it can only be read on one channel. With two mux units that could be done.

    All of the native analog pins could be read in pairs - based on proper channel association.

    16 on MUX and 6 on native pins could be interleaved to some degree, especially if the 6 other pins are available on the 'other' channel different from the MUX input pin

    there is a piezo drum sample reading lots of paired channels sample I wrote - and revisited recently - using the ADC library.

    This looks to be that thread and some code that is not at all directed at this problem but could morph it seems:
    pjrc.com/threads/61561-Teensy-4-Global-vs-local-variables-speed-of-execution

    Rather than indexing the PIN on BOTH channels it would use one channel for the mux and change the digital address pins, and then on the other channel ( where the pins can be found } it would change the pin# and then initiate the no wait read and return when they are complete and continue the cycle. Again some short wait for the MUX output to change/settle would be needed it seems before starting the read.

  5. #5
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    1,090
    > a way of testing how fast my code is running

    +1 on measuring before you start optimizing.

    digitalWrite(3, LOW); //S1 //0000
    ...
    digitalWrite(3, LOW); //S1

    You are doing a lot of writes that do nothing. But it won't make much difference.

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,701
    Check the MUX sheet - it may note some time before output is stable after input changes. That time should be honored before the read or the value will not be true.

    If the MUX works well enough - putting 11 input on two of them could present them to a pair of analog inputs with one on ADC0 and the other on ADC1

    The same address lines could feed both MUX's

    Then there would be symmetry in the read cycle process:
    > set Mux address
    > wait for MUX settling stable output
    > start both ADC channel Async reads
    -->> Return when reads complete and repeat indexing MUX inputs 1 through 11

    Linked ADC code was reading "10 pins read 157556 times per second "
    > that would be slowed by the MUX cycle time - Some microseconds delay for output settling time

    The ADC read happens in the background so those cycles are free to use manipulating the data.

    If the current setup is better than 2 MUX units - then 6 pins on one channel and the MUX on the other that should work as well - just proportionately longer for the cycle of 16 to complete as p#4 suggests

  7. #7
    Member
    Join Date
    Apr 2020
    Location
    HyŤres, France
    Posts
    25
    Hi
    I`m using the CD74HC4067 16 channel MUX. According to the data sheet there is a “Break-Before-Make” Switching time of 6ns (Typ) at 4.5V, so I have added a 10uS delay between switching channels, should be plenty. I will also simplify my digitalWrites (thanks jonr for pointing this out).

    This might sound like a silly question but how fast will my code be circulating, am I write to assume the code runs at the speed of the Teensy clock, which for a Teensy 3.2 will be 72MHz?

  8. #8
    Member
    Join Date
    Apr 2020
    Location
    HyŤres, France
    Posts
    25
    Hi

    Would this be a correct assumption:

    ADC Clock Teensy 3.2 = 400Khz

    1 / 400Khz = 2.5uS
    So the ADC can sample a sensor value every 2.5uS.

    ADC0 needs to sample 11 sensors before sending the data through USBMidi, so if

    11 * 2.5uS = 27.5uS. This is the time it will take to sample all 11 sensors, theoretically.

    does this sound correct?

  9. #9
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    1,090
    With a few lines of code, you could measure (vs assume). Search for ARM_DWT_CYCCNT.

Posting Permissions

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