Forum Rule: Always post complete source code & details to reproduce any issue!
Page 5 of 5 FirstFirst ... 3 4 5
Results 101 to 116 of 116

Thread: Teensy 4.0 which pins for which ADC

  1. #101
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    @defragster - yep it would make sense to add. I mainly put in the else stuff including the is Complete as a quick and dirty test to make sure my settings were not screwed up, such that the conversion/collection time does not exceed the interval time.

    I was trying to decide how far to take it, example could aim it toward the other thread, and see about, how well I could write the data out to SDCard...

    Example could setup to read N channels at some rate and see how long I might be able to write to the SD card before I run out of memory... That is for example the code could allocate lets say a buffer size that works well with SDFat. When the Interval timer, fills this buffer, it will add it to a linked list of items waiting for the main loop to take items off the list and do a write to the SDCARD. In the mean time the Interval timer will look at another chain for free buffers, If none available, malloc a new one... When SDCard finishes the write, it puts that buffer onto the free list...

    Question is, is this something I feel like trying or not? Likewise what format to store the data. Should all of the analog channels be interspersed, or do you write separate blocks for each analog channel. Like maybe where each block on SD has maybe has some header data like; which Analog, count, checksum? ... Or probably KISS!...

    But again do I feel like doing it? I am not sure... So many other possible fun distractions. Although maybe it would test my T4's sdcard... But now need to figure out what to add to test on the 2" ST7789 display

  2. #102
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,110
    Just seeing if I paid enough attention to read the code right Maybe I'll get a chance to work with it.

    I'd say super … KISsS. If there are read not ready fails - mark them for spacing and read to blocks of 512KB for SD write test would be good. Keeping the data mixed would fill usable blocks faster without having multiple active for reading into, would simplify the queueing of blocks to SD write and return for read use.

    Will be interesting to see it work on a twin pair of 6's for that other 'simple' log thread

  3. #103
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    Yep - I have a hacked up version now, that is reasonably KISS... It compiles, but I have not tried it yet:
    Code:
    /*
        This example shows how to use the IntervalTimer library and the ADC library in the Teensy 4.
    
        It uses the SD library to try to write the data to disk.
    
    */
    #include "ADCL_t4.h"
    #include <IntervalTimer.h>
    #include <SD.h>
    #include <SD_t3.h>
    
    const int ledPin = LED_BUILTIN;
    //-----------------------------------------------------------------
    // Define some of the analog settings, like which pins, how fast...
    //-----------------------------------------------------------------
    const uint8_t ADC0_pins[] = {A0, A1};
    const uint8_t ADC1_pins[] = {A2, A3};
    #define COUNT_PINS_PER_ADC  sizeof(ADC0_pins)
    
    const int interval_period = 100; // us
    ADCL *adc = new ADCL(); // adc object
    
    IntervalTimer timer; // timers
    
    //-----------------------------------------------------------------
    // SD file info
    //-----------------------------------------------------------------
    File log_file;
    char file_name[80] = "RAWANALOG.DAT";
    //-----------------------------------------------------------------
    // Define a link list of buffers for us to store data in
    //-----------------------------------------------------------------
    typedef struct _sample_buffer_t{
        volatile struct _sample_buffer_t *next;  // pointer to next one...
        uint16_t buffer[256];   // buffer of samples to write to disk 512 bytes...
    } sample_buffer_t;
    
    volatile sample_buffer_t *current_adc_buffer = nullptr;
    volatile sample_buffer_t *first_buffer_to_write_to_sd = nullptr;
    volatile sample_buffer_t *free_buffers = nullptr;
    
    //-----------------------------------------------------------------
    // Other globals
    //-----------------------------------------------------------------
    volatile uint8_t ADCPinIndex = 0;
    volatile uint16_t adc_samples_buffer_index = 0;
    
    volatile bool continue_to_collect_data = false;
    volatile bool samples_completed = false;
    uint32_t start_time;
    uint32_t last_report_time;
    uint32_t count_buffers_output;
    
    //-----------------------------------------------------------------
    // Forward references.
    //-----------------------------------------------------------------
    extern void timer_callback(void);
    
    
    //==============================================================
    // setup: Arduino setup function
    //==============================================================
    void setup() {
    
        pinMode(ledPin, OUTPUT); // led blinks every loop
        while (!Serial && millis() < 4000) ;
        Serial.begin(9600);
    
        delay(1000);
    
        ///// ADC0 ////
        Serial.printf("Configure ADC 1 and 2");
        adc->setAveraging(8); // set number of averages
        adc->setResolution(12); // set bits of resolution
        adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
        adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // change the sampling speed
        adc->setAveraging(8); // set number of averages
        adc->setResolution(12); // set bits of resolution
        adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
        adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // change the sampling speed
        Serial.println("Press any key to run test");
        allocate_timer_buffer();    // make sure we have a buffer for the timer. 
        delay(500);
    }
    
    //==============================================================
    // Loop: Main Arduino loop
    //==============================================================
    void loop() {
    
        // First test is to run 512 samples of each analog
        if (Serial.available()) {
            while (Serial.read() != -1) ;
            // first pass just toggle on/off test
            if (!continue_to_collect_data) {
                // Lets try to open the SD File...
                log_file = SD.open(file_name, FILE_WRITE);
                if (!log_file) {
                    Serial.println("*** Failed to create SD file ***");
                    return;
                }
    
                samples_completed = false;
                ADCPinIndex = 0;
    
                last_report_time = start_time = millis();
                count_buffers_output = 0;
    
                adc->adc0->startSingleRead(ADC0_pins[ADCPinIndex]);
                adc->adc1->startSingleRead(ADC1_pins[ADCPinIndex]);
                Serial.println("Starting Timer");
                if (!timer.begin(timer_callback, interval_period)) {
                    Serial.println("Failed to start interval timer");
                } else {
                    Serial.println("Timer started");
                    continue_to_collect_data = true;
                }
            } else {
                // we should try to kill the timer...
                continue_to_collect_data = false;  
            }
        }
    
        // See if we have any data to try to write out to SD Card.
        if (first_buffer_to_write_to_sd) {
            digitalWriteFast(ledPin, !digitalReadFast(ledPin));
            volatile sample_buffer_t *buffer_to_write = first_buffer_to_write_to_sd;
    
            log_file.write((uint8_t*)buffer_to_write->buffer, 512); // note should parameterize size here
            count_buffers_output++;
            __disable_irq();
            first_buffer_to_write_to_sd = buffer_to_write->next;    // unlink us
            buffer_to_write->next = free_buffers;
            free_buffers = buffer_to_write;
            __enable_irq();
        } else  if (samples_completed) {
            Serial.printf("collection ended after %d seconds with output count: %d\n", millis() - start_time, count_buffers_output);
            samples_completed = false;  // only report once
        }
        if (continue_to_collect_data && ((millis()-last_report_time) > 5000)) {
            Serial.printf("Running for %d seconds output count: %d\n", millis() - start_time, count_buffers_output);
            last_report_time = millis();
        }
        delay(10);
    }
    
    //==============================================================
    // allocate_timer_buffer:
    //==============================================================
    bool allocate_timer_buffer() {
        //__disable_irq();
        if (free_buffers) {
            current_adc_buffer = free_buffers;
            free_buffers = free_buffers->next;
        } else {
            current_adc_buffer = (sample_buffer_t*)malloc (sizeof(sample_buffer_t));
        }
        //__enable_irq();
        if (current_adc_buffer) {
            current_adc_buffer->next = nullptr;
            adc_samples_buffer_index = 0;
            return true;     
        }
        return false;
    }
    
    //==============================================================
    // Timer callback
    //==============================================================
    void timer_callback(void) {
    
        if (!current_adc_buffer) {
            if (!allocate_timer_buffer()) {
                // something wrong!
                timer.end();
                continue_to_collect_data = false;
                samples_completed = true;
            }
    
        }
        // try to grab data from ADC_0
        if (adc->adc0->isComplete()) {
            current_adc_buffer->buffer[adc_samples_buffer_index++] = adc->adc0->readSingle();
        } else {
            Serial.println("ADC_0: did not complete");
            current_adc_buffer->buffer[adc_samples_buffer_index++] = 0xffff;
        }
        if (adc->adc1->isComplete()) {
            current_adc_buffer->buffer[adc_samples_buffer_index++] = adc->adc1->readSingle();
        } else {
            Serial.println("ADC_1: did not complete");
            current_adc_buffer->buffer[adc_samples_buffer_index++] = 0xffff;
        }
    
        // Again should paramertize this... 
        if (adc_samples_buffer_index == 256) {
            // Have a full buffer... 
            // Should add it to the end of the list for main code to process.
            if (first_buffer_to_write_to_sd) {
                volatile sample_buffer_t *psb = first_buffer_to_write_to_sd;
                while (psb->next) psb = psb->next;
                psb->next = current_adc_buffer;
            } else {
              first_buffer_to_write_to_sd = current_adc_buffer;
            }
            if (continue_to_collect_data) {
                if (!allocate_timer_buffer()) continue_to_collect_data = false;
            }    
            if (!continue_to_collect_data) {
                timer.end();
                samples_completed = true;
            }
        }
        if (current_adc_buffer) { // something to test to know we are still active...
            ADCPinIndex++;
            if (ADCPinIndex >= sizeof(ADC0_pins)) ADCPinIndex = 0;
            adc->adc0->startSingleRead(ADC0_pins[ADCPinIndex]);
            adc->adc1->startSingleRead(ADC1_pins[ADCPinIndex]);
        }
    }

  4. #104
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,315
    @KurtE
    Gave it test spin. Having a problem with the SD card believe it or not. Card gets initialized but comes back that it can't create the file. So I ran the datalogger example from the SD card library and it worked fine, file created and had data in it. tried a couple of things but something is not quite right. Going to keep looking though.

  5. #105
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,110
    Where is the latest tree? github.com/KurtE/ADCL_t4/tree/Comapre-WIP

    Any other needed changes for it to run work? Current CORES?

  6. #106
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    FYI - I changed over to SDFat Beta...

    Code:
    /*
        This example shows how to use the IntervalTimer library and the ADC library in the Teensy 4.
    
        It uses the SD library to try to write the data to disk.
    
    */
    #include "ADCL_t4.h"
    #include <IntervalTimer.h>
    //#include <SD.h>
    #include "SdFat.h"
    #define SD_FAT_TYPE 3
    
    const int ledPin = LED_BUILTIN;
    //-----------------------------------------------------------------
    // Define some of the analog settings, like which pins, how fast...
    //-----------------------------------------------------------------
    const uint8_t ADC0_pins[] = {A0, A1};
    const uint8_t ADC1_pins[] = {A2, A3};
    #define COUNT_PINS_PER_ADC  sizeof(ADC0_pins)
    
    const int interval_period = 500; // us
    ADCL *adc = new ADCL(); // adc object
    
    IntervalTimer timer; // timers
    
    //-----------------------------------------------------------------
    // SD file info
    //-----------------------------------------------------------------
    //File log_file;
    SdFs sd;
    FsFile log_file;
    
    char file_name[80] = "datalog.txt";
    //-----------------------------------------------------------------
    // Define a link list of buffers for us to store data in
    //-----------------------------------------------------------------
    typedef struct _sample_buffer_t {
      volatile struct _sample_buffer_t *next;  // pointer to next one...
      uint16_t buffer[256];   // buffer of samples to write to disk 512 bytes...
    } sample_buffer_t;
    
    volatile sample_buffer_t *current_adc_buffer = nullptr;
    volatile sample_buffer_t *first_buffer_to_write_to_sd = nullptr;
    volatile sample_buffer_t *free_buffers = nullptr;
    uint32_t count_buffers_allocated = 0;
    
    //-----------------------------------------------------------------
    // Other globals
    //-----------------------------------------------------------------
    volatile uint8_t ADCPinIndex = 0;
    volatile uint16_t adc_samples_buffer_index = 0;
    
    volatile bool continue_to_collect_data = false;
    volatile bool samples_completed = false;
    uint32_t start_time;
    uint32_t last_report_time;
    uint32_t count_buffers_output;
    
    //-----------------------------------------------------------------
    // Forward references.
    //-----------------------------------------------------------------
    extern void timer_callback(void);
    
    
    //==============================================================
    // setup: Arduino setup function
    //==============================================================
    void setup() {
    
      pinMode(ledPin, OUTPUT); // led blinks every loop
      while (!Serial && millis() < 4000) ;
      Serial.begin(9600);
    
      delay(1000);
    
      ///// ADC0 ////
      Serial.printf("Configure ADC 1 and 2");
      adc->setAveraging(8); // set number of averages
      adc->setResolution(12); // set bits of resolution
      adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
      adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // change the sampling speed
      adc->setAveraging(8); // set number of averages
      adc->setResolution(12); // set bits of resolution
      adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
      adc->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // change the sampling speed
      Serial.println("Press any key to run test");
      allocate_timer_buffer();    // make sure we have a buffer for the timer.
      delay(500);
    }
    
    //==============================================================
    // Loop: Main Arduino loop
    //==============================================================
    void loop() {
    
      // First test is to run 512 samples of each analog
      if (Serial.available()) {
        while (Serial.read() != -1) ;
        // first pass just toggle on/off test
        if (!continue_to_collect_data) {
          // Lets try to open the SD File...
          if (!sd.begin(SdioConfig(DMA_SDIO))) {
            Serial.println("** SD.begin failed ***");
          }
          delay(250);
          
          if (!log_file.open(file_name, O_RDWR | O_CREAT)) {
            Serial.printf("*** Failed to create SD file (%s) ***\n", file_name);
            return;
          }
    
          samples_completed = false;
          ADCPinIndex = 0;
    
          last_report_time = start_time = millis();
          count_buffers_output = 0;
    
          adc->adc0->startSingleRead(ADC0_pins[ADCPinIndex]);
          adc->adc1->startSingleRead(ADC1_pins[ADCPinIndex]);
          Serial.println("Starting Timer");
          if (!timer.begin(timer_callback, interval_period)) {
            Serial.println("Failed to start interval timer");
          } else {
            Serial.println("Timer started");
            continue_to_collect_data = true;
          }
        } else {
          // we should try to kill the timer...
          continue_to_collect_data = false;
        }
      }
    
      // See if we have any data to try to write out to SD Card.
      if (first_buffer_to_write_to_sd) {
        digitalWriteFast(ledPin, !digitalReadFast(ledPin));
        volatile sample_buffer_t *buffer_to_write = first_buffer_to_write_to_sd;
    
        log_file.write((uint8_t*)buffer_to_write->buffer, 512); // note should parameterize size here
        count_buffers_output++;
        __disable_irq();
        first_buffer_to_write_to_sd = buffer_to_write->next;    // unlink us
        buffer_to_write->next = free_buffers;
        free_buffers = buffer_to_write;
        __enable_irq();
      } else  if (samples_completed) {
        Serial.printf("collection ended after %d seconds with output count: %d\n", millis() - start_time, count_buffers_output);
        samples_completed = false;  // only report once
      }
      if (continue_to_collect_data && ((millis() - last_report_time) > 5000)) {
        Serial.printf("Running for %d seconds output count:%d buffers allocated: %d\n", millis() - start_time, count_buffers_output, count_buffers_allocated);
        last_report_time = millis();
      }
      delay(10);
    }
    
    //==============================================================
    // allocate_timer_buffer:
    //==============================================================
    bool allocate_timer_buffer() {
      //__disable_irq();
      if (free_buffers) {
        current_adc_buffer = free_buffers;
        free_buffers = free_buffers->next;
      } else {
        current_adc_buffer = (sample_buffer_t*)malloc (sizeof(sample_buffer_t));
        count_buffers_allocated++;
      }
      //__enable_irq();
      if (current_adc_buffer) {
        current_adc_buffer->next = nullptr;
        adc_samples_buffer_index = 0;
        return true;
      }
      return false;
    }
    
    //==============================================================
    // Timer callbck
    //==============================================================
    void timer_callback(void) {
    
      if (!current_adc_buffer) {
        if (!allocate_timer_buffer()) {
          // something wrong!
          timer.end();
          continue_to_collect_data = false;
          samples_completed = true;
        }
    
      }
      // try to grab data from ADC_0
      if (adc->adc0->isComplete()) {
        current_adc_buffer->buffer[adc_samples_buffer_index++] = adc->adc0->readSingle();
      } else {
        Serial.println("ADC_0: did not complete");
        current_adc_buffer->buffer[adc_samples_buffer_index++] = 0xffff;
      }
      if (adc->adc1->isComplete()) {
        current_adc_buffer->buffer[adc_samples_buffer_index++] = adc->adc1->readSingle();
      } else {
        Serial.println("ADC_1: did not complete");
        current_adc_buffer->buffer[adc_samples_buffer_index++] = 0xffff;
      }
    
      // Again should paramertize this...
      if (adc_samples_buffer_index == 256) {
        // Have a full buffer...
        // Should add it to the end of the list for main code to process.
        if (first_buffer_to_write_to_sd) {
          volatile sample_buffer_t *psb = first_buffer_to_write_to_sd;
          while (psb->next) psb = psb->next;
          psb->next = current_adc_buffer;
        } else {
          first_buffer_to_write_to_sd = current_adc_buffer;
        }
        if (continue_to_collect_data) {
          if (!allocate_timer_buffer()) continue_to_collect_data = false;
        }
        if (!continue_to_collect_data) {
          timer.end();
          samples_completed = true;
        }
      }
      if (current_adc_buffer) { // something to test to know we are still active...
        ADCPinIndex++;
        if (ADCPinIndex >= sizeof(ADC0_pins)) ADCPinIndex = 0;
        adc->adc0->startSingleRead(ADC0_pins[ADCPinIndex]);
        adc->adc1->startSingleRead(ADC1_pins[ADCPinIndex]);
      }
    }
    Which is showing some outputs. I changed timer interval to 500, so should interrupt 2000 times per second, with two readings, so about 4000 samples per second recorded.

    I have not verified the data on the SDCARD yet, but maybe good enough to push up to github...

    EDIT: Pushed example up to github... Note I am in master branch...

  7. #107
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    @mjs513, @defragster... I extracted my DMA processing out of my example sketch and into some external files.

    I think the example app is still working OK... let me know what you think.

    Kurt
    Last edited by defragster; Today at 01:44 AM. Reason: r

  8. #108
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,315
    @KurtE
    Been playing with the updated lib. Tried everything but the logger sketch:
    1. Compare sketch works but there is an error I had to fix. Looks like you have the outdated sketch: analogReadCmp -> analogRead
    2. Continuous example works, nothing broke
    3. RMS sketch still works
    4. DMA - doesn't seem to be working. ISR not firing - have to go back and see the old one still works.

    Logger sketch - will test in the morning.

    Mike

  9. #109
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,110
    What //#include "SdFat.h" ??

    Had to comment it out - got the latest https://github.com/greiman/SdFat-beta and compile grief

  10. #110
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,315
    @KurtE - @defragster

    I copied the sketch in post #106 and downloaded the latest core files as well as the latest SDFat lib. Compiled with out issue I did have to make one change;
    [CODE] } else if (samples_completed) {
    Serial.printf("collection ended after %d seconds with output count: %d\n", millis() - start_time, count_buffers_output);
    samples_completed = false; // only report once
    log_file.close();
    Serial.println(F("Done"));[
    /CODE] added log_file close, if I didn't and I ended the test the file would be empty. But now here is the problem, the resultant text file is all gibberish - not sure what format the data is in?

    EDIT: Looking at SDfat advdatalogger example think the file created is a binary file format.
    Last edited by mjs513; Today at 12:37 PM.

  11. #111
    Senior Member
    Join Date
    Feb 2015
    Location
    Finland
    Posts
    134
    Sorry for interrupting (pun not intended), but I recently verified the following approach works on Teensy 3.2.

    • The ADCx is in software trigger mode.
    • One DMA channel is used to transfer samples from ADCx_R0 register to a DMA buffer, triggered by the DMAMUX_SOURCE_ADCx hardware trigger, i.e. whenever ADCx conversion is complete.
    • Another DMA channel is used to transfer ADC channel selectors from a circular buffer to register ADCx_SC1A ( ADCx_HC0 for Teensy 4.0). Because the ADC is in software trigger mode, this triggers a new conversion.

    The interesting thing here is that no interrupts are needed at all for continuous operation, which should cause the least interference with other stuff, like SD card access.

    I believe that for Teensy 3.2, TPM2 is the optimum choice to generate the trigger events for the second DMA channel. If both ADCs are used, they will sample at the same rate, using the two channels of TPM2 to choose the relative phase of the sampling triggers. I still have to verify this part and clean up the code for public view, though. The sampling is extremely regular, with minimal jitter. To use both ADCs at the same total sample rate, TPM2 and four DMA channels suffice, which is nice.

    Both DMA channels can use a circular buffer. For the sample buffer, the .TCD->CITER_ELINKNO field of the DMAChannel object can be used to track the current position (assuming buffer is at most 32767 samples long, otherwise you need to link DMA channels). You do need to use a separate DMASettings object to replace the DMAChannel settings on completion for circular buffer operation. (If you use the settings in the DMAChannel itself, it will just get stuck on the last transfer.)

    The sampled input pin order or density is arbitrary -- you can do e.g. [ A2, A3, A2, A12 ] to get A2 at twice the sample rate of A3 and A12 --, but the samples will be interleaved in the DMA buffer. (The source DMA buffer size is not tied to the size of the sample buffer in any way.)

    When applying changes, the only race window is the possible completion of the last ADC sample. This can be avoided by stopping the timer first, then the second DMA channel, and then disabling the conversion by selecting the disable channel by writing 31 to ADCx_SC1A on Teensy 3.2 or ADCx_HC0 on Teensy 4.0, and finally stopping the first DMA channel. When starting, the timer should be enabled last. This gives a very well controlled, robust implementation.

    The annoying part is to determine the mapping between pins to ADCx channels.
    Code:
    Teensy 3.2 analog input ADC channel mapping:
    
    Teensyduino     Pin         ADC0 Channel    ADC1 Channel
     14 A0          PTD1         5
     15 A1          PTC0        14
     16 A2          PTB0         8               8
     17 A3          PTB1         9               9
     18 A4          PTB3        13
     19 A5          PTB2        12
     20 A6          PTD5         6
     21 A7          PTD6         7
     22 A8          PTC1        15
     23 A9          PTC2         4
     34 A10         ADC0_DP0     0
     35 A11         ADC0_DM0    19
     36 A12         ADC0_DP3     3               0
     37 A13         ADC0_DM3    21              19
     40 A14         DAC0        23
     26 A15         PTE1       (Not supported, would require MUXSEL=0)
     27 A16         PTC9                         5
     28 A17         PTC8                         4
     29 A18         PTC10                        6
     30 A19         PTC11                        7
     31 A20         PTE0       (Not supported, would require MUXSEL=0)
     38             TEMP        26              26
                    BANDGAP     27              27
                    VREFH       29              29
                    VREFL       30              30
                    1.2VREF     22              18
    
    PGA uses channel 2 for both ADCs.
    I do also have a 4.0 and according to the datasheet, the same approach works there; I just haven't verified it in practice.
    Code:
    Teensy 4.0 analog input ADC channel mapping:
    
    Teensyduino     Pin         ADC1 Channel    ADC2 Channel
     14 A0          AD_B1_02     7               7
     15 A1          AD_B1_03     8               8
     16 A2          AD_B1_07    12              12
     17 A3          AD_B1_06    11              11
     18 A4          AD_B1_01     6               6
     19 A5          AD_B1_00     5               5
     20 A6          AD_B1_10    15              15
     21 A7          AD_B1_11     0               0
     22 A8          AD_B1_08    13              13
     23 A9          AD_B1_09    14              14
     22 A10         AD_B0_12     1
     23 A11         AD_B0_13     2
     23 A12         AD_B1_14                     3
     24 A13         AD_B1_15                     4
    Has anyone collated similar tables for LC, 3.0/3.1, 3.5, and/or 3.6?

    If you were already well aware of this method, apologies for stating the obvious!
    Perhaps we could format the information in nice tables for a sticky post or a Teensyduino Reference page at the PJRC website?
    Last edited by Nominal Animal; Today at 02:04 PM.

  12. #112
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    Quote Originally Posted by mjs513 View Post
    @KurtE - @defragster

    I copied the sketch in post #106 and downloaded the latest core files as well as the latest SDFat lib. Compiled with out issue I did have to make one change;
    [CODE] } else if (samples_completed) {
    Serial.printf("collection ended after %d seconds with output count: %d\n", millis() - start_time, count_buffers_output);
    samples_completed = false; // only report once
    log_file.close();
    Serial.println(F("Done"));[
    /CODE] added log_file close, if I didn't and I ended the test the file would be empty. But now here is the problem, the resultant text file is all gibberish - not sure what format the data is in?

    EDIT: Looking at SDfat advdatalogger example think the file created is a binary file format.
    Yep - Thanks, I forgot to put the close in...

    Yep - Currently a binary format, 2 bytes per sample.

    Obviously we could hack this up more to have something like a CSV file. Would add a little complexity of not having buffers fill the same, probably keep a size field in the buffer structure, and either tell system to write them when they are filled or at some percentage full, ... Do you think it would make it more useful as an example? Could make it a choice in the code...

  13. #113
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    @nominal animal - DMA examples - There is sort of an example for doing DMA with both ADCs that is part of the ADC library

    There are issues, with the ringBufferDMA as part of that project... I had my own code for T3.5/6 that used the DMA with a PDB... with two on each one, that I toggled between...

    Still working on T4 stuff in our probably temporary project ADCL_t4, where I have my own DMA buffer class...
    As for interrupts, I do have this code setup to interrupt as each buffer is completed. One could set this up to not interrupt and do query, but I don't think one interrupt per in the case I was playing at something like 3000 samples is going to be too bad.

    Analog IO pins: Have you looked at the main forum page that Pedro setup for the ADC library? https://forum.pjrc.com/threads/25532...for-Teensy-3-1
    If you scroll down the page, there is a section talking about pins.


    I also have some of my own excel documents, which I have done during each of the more recent beta time frames that are now up at: https://github.com/KurtE/TeensyDocuments
    The T4 document has a column that shows the Analog pins. like 14/A0 pin is on A1:7 and A2:7 ...

    The K66 Beta file (T3.6/T3.5) has sheets labeled like Pin Mux Table T3.6, and in this it shows for example: Pin 14: ADC0_SE5b Which you can deduce the data from...

  14. #114
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    4,315
    Quote Originally Posted by KurtE View Post
    Yep - Thanks, I forgot to put the close in...

    Yep - Currently a binary format, 2 bytes per sample.

    Obviously we could hack this up more to have something like a CSV file. Would add a little complexity of not having buffers fill the same, probably keep a size field in the buffer structure, and either tell system to write them when they are filled or at some percentage full, ... Do you think it would make it more useful as an example? Could make it a choice in the code...
    Probably need to hack it up to write it as a CSV file, would be easier to the read the data from the file. The other possibility is that I started hacking up Bill G's code to read a binary file and the write a csv or view the data. Having a problem with the SD card. Also not 100% sure about what the metadata is. Problem it is not seeing any files on the card. Here it is if you want to play:

    AdvDataLoggerRead.zip

    meta data is really then 2bytes per pincount. so for adc0 and adc1 pincount = 4 would be 4x2. And that is all that is being written.

  15. #115
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    @mjs513 - Yep I am hacking up my example sketch to allow it to either output CSV or raw...
    Would make it easier to look at...

  16. #116
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,745
    @mjs513, @defragster...- I updated the test program, to give option to output binary or CSV files.

    Also allows you to type in name of file...
    If first character of line is a , the file will output CSV.
    If first char is # it will output binary.

    Characters after that are file name.
    Simply entering CR - will default to last file name and last format...

Posting Permissions

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