Forum Rule: Always post complete source code & details to reproduce any issue!
Page 3 of 17 FirstFirst 1 2 3 4 5 13 ... LastLast
Results 51 to 75 of 416

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

  1. #51
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    A few other comments:

    ADC0_CFG1 = 0b00000000;
    This means you are running the ADC with a speed of 48 MHz, the specs limit for resolutions less than 16 bits is 18 MHz, so you are running at 3 times the maximum speed! The manual doesn't say if this can lead to actual physical damage of the ADC, or only loss of precision. It's true that you're using the ADHSC bit though, but adding 2 ADCK at 48 MHz (0.04 us!) won't probably be enough (I think min time for a conversion is around 1 us). If it works for you then it's fine, but I mention it so you know that maybe the ADC fails under the stress sooner than it should.

    Waiting for calibration to finish. The documentation is confused as to what flag to be waiting for (SC3[CAL] on page 663 and SC1n[COCO] on page 687+688)
    When the calibration finishes it sets SC3[CAL] AND SC1n[COCO], so you could check either, but it makes more sense to check SC3[CAL] (and SC3[CALF] to make sure the calibration was successful), as you do.

    An idea to make it run even faster (I haven't really thought about this in detail):
    Start a continuous measurement on both ADCs using pins A2, and A3 (for example) in the setup already.
    In the loop:
    - store the values value1,value2.
    - start a normal measurement on pins A11, A10 and get the value (like you do now).
    - start a continuous measurement again on pins A2, A3.
    - process data.

    This algorithm is faster if the time that it takes to start the continuous measurement is less than the total time of highSpeed8bitAnalogReadMacro(...), which I think is the case. You'd be measuring the new values of A2, A3 while doing you processing!
    To start the continuous thingy you set SC3[ADCO] and write to SC1A.


    I read a little bit about your project and you said that you wrote some java program to log the values from the Teensy, I'm interested in something like that to test the ADC in a more systematic way. Can you give me a copy and some instructions on how to use it? (I've never used java).


    I'm preparing a big update for the library adding support for different conversion and sampling speeds, adding more synchronous methods (single-ended, differential, both single-shot and continuous), and using bitband for atomic access to the registers so everything is interrupt safe. I won't include methods for analog timers, but there will be examples on how to use IntervalTimer.

  2. #52
    Junior Member
    Join Date
    Jun 2014
    Posts
    1
    pedvide,

    This is a very useful library for the Teensy 3.1. I would like to use it for some projects that I am doing. However, there is no license information in the code that would allow others to use it, whether that be MIT or LGPL or freely released with needed attribution like much of Paul's code. Could you clarify the license for this library and perhaps add it to the code?

    Thanks!

  3. #53
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    drbm:

    I hadn't thought about that. I've been reading about the different licenses and I'm thinking of going with LGPL. I understand that this license allows anybody to use the library, even for commercial stuff but if you modify the library itself then your modified copy is also free software (so you have to release the code with all changes).

  4. #54
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,654
    I usually use MIT license for code that gets compiled into firmware. Sometimes I add an extra attribution request or requirement, but still basically MIT.

  5. #55
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    Big update!

    Finally I've pushed to github a big update with the following new features:

    - Conversion and sampling speed select.
    - More synchronized methods.
    - Better initial calibration.
    - Bitband access, so all functions are interrupt safe

    The analog timers aren't supported anymore, they add a lot of complexity to the code. The example analogReadIntervalTimer shows how to use timers with this library.

    I've updated the 1st post with all the new information, make sure to check it out.

    The license for the library is the MIT.
    Last edited by Pedvide; 06-15-2014 at 01:46 PM.

  6. #56
    Senior Member
    Join Date
    Feb 2013
    Posts
    179
    Thanks for the update, can't wait to try it out. Just wondering, for PGA, do we now use 2,4,8 etc...instead of 0-6 like before? Also, was wondering about calling compare. For my measurements, I only care about the raw data and not interested in the actual voltage. If this is the case, do I need to worry about calling these functions?
    Last edited by turtle9er; 06-15-2014 at 07:10 PM.

  7. #57
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    turtle9er:

    Yes, originally I programmed the PGA thing very quickly, but now I realized that it was a bit confusing that PGA 1 means 2x, 2=4x, etc, so now PGA 2 means 2x, 4=4x, etc.

    The compare functions are useful when you only need to "control" some kind of sensor, or battery, so you are interested in voltages above or below some value, but not the rest.
    If you want to know the voltage at all times you don't need them! It just saves a comparison in software.

  8. #58
    Senior Member
    Join Date
    Feb 2013
    Posts
    179
    Hi Pedvide,

    I finally got to testing the syncro function and now it works. However I have attached the output I had from reading a voltage divider on two pins A2 and A3. So, the same voltage should of been seen at both pins, however I was not getting similar results. Thanks again for all your hard work in this library, it has made my life easier, that is for sure.

    Syncro_ADC_test.txt

  9. #59
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    Please post the final code with which you got that result and also the schematics of your system! (a picture is probably fine).
    What's the value of the resistors in your voltage divider?

  10. #60
    Senior Member
    Join Date
    Feb 2013
    Posts
    179
    I was just using a 100k trim pot, thing the ratio was 33/67. Is this too high of a resistor? I was worried about using low values and then it drawing more current from the batteries. I will be in the lab tomorrow, and I will try your provided code and see what results that give me. I personally am not using this method right now, it was during helping another forum member that I saw this result.

    Code:
    /*
    ECG measurement Project:
    - Sensing two ADC values,
    - Analog files being logged on sd card
        Time  A-B  A  B
    */
    
    //Including Libraries
    #include <ADC.h>
    #include <string.h>
    #include <Time.h>  
    #include <SdFat.h>
    #include <SdFatUtil.h>
    #include <BufferedWriter.h>
    SdFat sd;
    SdFile myFile;
    
    //Teensy 3.1 has the LED on pin 13
    const int ledPin = 13;
    const int readPin0 = A2;  //ADC read A2
    const int readPin1 = A3;  //ADC read A3
    const int chipSelect = SS;
    //char filename[] = "00000000.txt";
    #define SD_CHIP_SELECT  10  // SD chip select pin
    #define error(s) sd.errorHalt_P(PSTR(s))
    #define FILE_BASE_NAME "CHOP" //Can be max size of 5 character, XXXXX000.BIN DOS 8.3 format
    #define TMP_FILE_NAME "TMP_LOG.BIN"
    const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
    const uint32_t FILE_BLOCK_COUNT = 500UL; //500=250kb 1 block=512bytes
    const uint32_t ERASE_SIZE = 262144L;
    uint32_t bgnBlock, endBlock;
    uint8_t*  pCache;
    char binName[13] = FILE_BASE_NAME "000.BIN";
    
    ADC *adc = new ADC(); // adc object
    ADC::Sync_result result;
    float ADCvalue_0 = ADC_ERROR_VALUE;
    float ADCvalue_1 = ADC_ERROR_VALUE;
    float SDBuffer [128];
    int count = 0;
    uint32_t bn = 1; //block number
    int startTime; //to reset milli count at each recording
    
    //Interval Timer
    IntervalTimer timer0;
    char c=0;
    
    //------------------------------------------------------------------------------
    /*
     * User provided date time callback function.
     * See SdFile::dateTimeCallback() for usage.
     */
    void dateTime(uint16_t* date, uint16_t* time) {
      // User gets date and time from GPS or real-time
      // clock in real callback function
      time_t now();
      // return date using FAT_DATE macro to format fields
      *date = FAT_DATE(year(), month(), day());
    
      // return time using FAT_TIME macro to format fields
      *time = FAT_TIME(hour(), minute(), second());
    }
    void createFile(){
    
      bn=1; //reset block count
      count=0;
      // Find unused file name.
      if (BASE_NAME_SIZE > 5) {
      }
      while (sd.exists(binName)) {
        if (binName[BASE_NAME_SIZE + 2] != '9') {
          binName[BASE_NAME_SIZE + 2]++; //changed from +1 since now 0-999 instead of 0-99
        } 
        else {
          binName[BASE_NAME_SIZE + 2] = '0';
          //binName[BASE_NAME_SIZE + 1]++;
          if (binName[BASE_NAME_SIZE+1] == '9') {
            binName[BASE_NAME_SIZE + 1] = '0';
            binName[BASE_NAME_SIZE ]++;
          }
          else{
          if (binName[BASE_NAME_SIZE] == '9') ;
          binName[BASE_NAME_SIZE + 1]++;
          }
        }
     
      }
     // Serial.println(binName);
      // delete old log file
      if (sd.exists(TMP_FILE_NAME)) {
        if (!sd.remove(TMP_FILE_NAME)) ;
      }
      // create new file
      myFile.close();
      if (!myFile.createContiguous(sd.vwd(),
      TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT));
      // get address of file on SD
      if (!myFile.contiguousRange(&bgnBlock, &endBlock));
      // use SdFat's internal buffer
      pCache = (uint8_t*)sd.vol()->cacheClear();
      if (pCache == 0); 
      memset(pCache, '0', 512); 
      // flash erase all data in file
      uint32_t bgnErase = bgnBlock;
      uint32_t endErase;
      while (bgnErase < endBlock) {
        endErase = bgnErase + ERASE_SIZE;
        if (endErase > endBlock) endErase = endBlock;
        if (!sd.card()->erase(bgnErase, endErase)) ;
        bgnErase = endErase + 1;
      }
    }
    
    time_t getTeensy3Time()
    {
      return Teensy3Clock.get();
    }
    
    void setup() {
      Serial.begin(115200);
      setSyncProvider(getTeensy3Time);
      SdFile::dateTimeCallback(dateTime);
      pinMode(ledPin, OUTPUT);
      pinMode(readPin0, INPUT);  //Read analog signal pin1
      pinMode(readPin1, INPUT);  //Read analog signal pin2
      
      //Set ADC (Averaging and Resolution)  
      adc->setAveraging(32); // 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
      //try low/med speed since load cell has high impedence
      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
     //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
     
      adc->setAveraging(32, 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
    
        
      // Initialize SdFat or print a detailed error message and halt
      // Use half speed like the native library.
      // change to SPI_FULL_SPEED for more performance.
      if (!sd.begin(chipSelect, SPI_FULL_SPEED)) sd.initErrorHalt();
    
      createFile();  
    }
    
    void loop() {
    //not sure how you start/stop data collection
      //Example using serial input
        if (Serial.available()) {
    	c = Serial.read();
    	if(c=='r') { // Start recording
            if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT))Serial.println("Recording") ;
            //digitalWrite(LED,ledValue);//Turn LED on to indicate recording if you want
            timer0.begin(timerCallback0, 40000); //start timer 4000=250sps
            startTime=millis();
        } else if(c=='s') { // stop recording
            stopRecording();  
        } 
    
      }
     delay(1);
    
    }
    
    void stopRecording(){
            timer0.end(); //Turn off timer to stop SD card write
            if (!sd.card()->writeStop())Serial.println("Stopped");
            // Truncate file if recording stopped early.
            if (bn != FILE_BLOCK_COUNT) {    
                if (!myFile.truncate(512L * bn)) ;
            }
            binaryToCsv();
            if (!myFile.rename(sd.vwd(), binName)) ;
            createFile(); 
    		}
    
    void timerCallback0(){
          result = adc->analogSynchronizedRead(readPin0, readPin1);
         float ADCvalue_0 = result.result_adc0*3.3/adc->adc0->getMaxValue();
         float ADCvalue_1 = result.result_adc1*3.3/adc->adc1->getMaxValue();
      if (count < 128){ //since using float values, 128x4=512bytes
      //Conversion issue fixed, so don't need code commented out below
       // && (result.result_adc0 !=ADC_ERROR_VALUE) && (result.result_adc1 !=ADC_ERROR_VALUE) 
        SDBuffer[count] = millis()-startTime; //if you don't get a start time, then will be time since program started
        SDBuffer[count+1] = ADCvalue_0-ADCvalue_1; 
        SDBuffer[count+2] = ADCvalue_0;
        SDBuffer[count+3] = ADCvalue_1;
            Serial.print("Time: ");
            Serial.print(SDBuffer[count]);
            Serial.print("\t"); 
            Serial.print("A-B: ");
            Serial.print(SDBuffer[count+1],DEC);  
            Serial.print("\t");  
            Serial.print("A: ");  
            Serial.print(SDBuffer[count+2],DEC);
            Serial.print("\t");  
            Serial.print("B: ");
            Serial.println(SDBuffer[count+3],DEC); 
        count = count + 4;//move index 4 positions for next values
      }
     
      if (count== 128){
       noInterrupts(); 
       memcpy(pCache, &SDBuffer, 512);
           if (!sd.card()->writeData((uint8_t*)pCache)) ;
        bn++; //increment block number
        count = 0; 
        memset(pCache, '0', 512); 
          interrupts();
      }
           
     
    }
    void binaryToCsv() {
      uint8_t lastPct = 0;
      float buf[128]; //changed to float
      //metadata_t* pm;
      uint32_t t0 = millis();
      uint32_t syncCluster = 0;
      SdFile csvFile;
      char csvName[13];
      BufferedWriter bw;
      
      if (!myFile.isOpen()) {
        Serial.println(F("No current binary file"));
        return;
      }
      myFile.rewind();
      // create a new csvFile
      strcpy(csvName, binName);
      strcpy_P(&csvName[BASE_NAME_SIZE + 3], PSTR(".CSV"));
    
      if (!csvFile.open(csvName, O_WRITE | O_CREAT | O_TRUNC)) {
        error("open csvFile failed");  
      }
      Serial.println();
      Serial.print(F("Writing: "));
      Serial.print(csvName);
      Serial.println(F(" - type any character to stop"));
      //pm = (metadata_t*)&buf;
      bw.init(&csvFile);
      bw.putStr_P(PSTR("Time,")); //Write header at top of file
      bw.putStr_P(PSTR("A-B,"));
      bw.putStr_P(PSTR("A,"));
      bw.putStr_P(PSTR("B"));
      bw.putCRLF();
    
      uint32_t tPct = millis();
      while (!Serial.available() && myFile.read(&buf, 512) == 512) {
        uint16_t i;
    	//read 512 bytes of data here ie:128 samples
        for (i = 0; i < 128; i++) {
          bw.putNum(buf[i],6); //Change 4 to what ever level of decimals you want
          if((i + 1)%4) { //since 4 data points, it put a comma between 3 points and on the 4th,send a carrige return
            bw.putChar(',');
          } else {
            bw.putCRLF();
          }
        }
        if (csvFile.curCluster() != syncCluster) {
          bw.writeBuf();
          csvFile.sync();
          syncCluster = csvFile.curCluster();
        }
    	//looks like code to print out % done
        if ((millis() - tPct) > 1000) {
          uint8_t pct = myFile.curPosition()/(myFile.fileSize()/100);
          if (pct != lastPct) {
            tPct = millis();
            lastPct = pct;
            Serial.print(pct, DEC);
            Serial.println('%');
          }
        }
        if (Serial.available()) break;
      }
      bw.writeBuf();
      csvFile.close();
      Serial.print(F("Done: "));
      Serial.print(0.001*(millis() - t0));
      Serial.println(F(" Seconds"));
    }

  11. #61
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,654
    100K is a pretty high source impedance. It can work, but the results will be noisy compared to a lower source impedance.

  12. #62
    Senior Member
    Join Date
    Feb 2013
    Posts
    179
    I was just using a setup for another project where I use a 33k/68k resistor to measure battery voltage level. I am not worried if too noisy, since I take the average of 1000 samples.

    For the collection I used the same divider and put it on the two pins. Just assumed they would be similar and found it odd how they both stayed consistent

    Went with higher divider values since didn't want too much current draw when measuring the battery. Do you suggest I keep the resistors under 10k, or is that still too high?

  13. #63
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    With high impedance you should use lower sampling speeds (adc->setSamplingSpeed(...); ) and see if the issue remains.

  14. #64
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    18,654
    Should this library be included with the Teensyduino installer?

    If you feel it's stable enough, where the 2-5 month release cycle for Teensyduino isn't a huge problem, I'd really like to include it.

  15. #65
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    Hi Paul,

    I'd be honored to have it included!
    The library is almost "done", the only things left to implement is the DMA stuff (and maybe PDB).

    What do you mean by "the 2-5 month release cycle for Teensyduino isn't a huge problem"? I imagine that I can still "publish" updates on github but that the Teensyduino version will only be updated every 2-5 months?

  16. #66
    Junior Member
    Join Date
    Jun 2014
    Posts
    3
    Just saw the answer now, sry for the late response.
    The java code for the project is available on the blog.
    If you need anything else feel free to drop me an email.

    Quote Originally Posted by Pedvide View Post
    A few other comments:

    ADC0_CFG1 = 0b00000000;
    This means you are running the ADC with a speed of 48 MHz, the specs limit for resolutions less than 16 bits is 18 MHz, so you are running at 3 times the maximum speed! The manual doesn't say if this can lead to actual physical damage of the ADC, or only loss of precision. It's true that you're using the ADHSC bit though, but adding 2 ADCK at 48 MHz (0.04 us!) won't probably be enough (I think min time for a conversion is around 1 us). If it works for you then it's fine, but I mention it so you know that maybe the ADC fails under the stress sooner than it should.


    When the calibration finishes it sets SC3[CAL] AND SC1n[COCO], so you could check either, but it makes more sense to check SC3[CAL] (and SC3[CALF] to make sure the calibration was successful), as you do.

    An idea to make it run even faster (I haven't really thought about this in detail):
    Start a continuous measurement on both ADCs using pins A2, and A3 (for example) in the setup already.
    In the loop:
    - store the values value1,value2.
    - start a normal measurement on pins A11, A10 and get the value (like you do now).
    - start a continuous measurement again on pins A2, A3.
    - process data.

    This algorithm is faster if the time that it takes to start the continuous measurement is less than the total time of highSpeed8bitAnalogReadMacro(...), which I think is the case. You'd be measuring the new values of A2, A3 while doing you processing!
    To start the continuous thingy you set SC3[ADCO] and write to SC1A.


    I read a little bit about your project and you said that you wrote some java program to log the values from the Teensy, I'm interested in something like that to test the ADC in a more systematic way. Can you give me a copy and some instructions on how to use it? (I've never used java).


    I'm preparing a big update for the library adding support for different conversion and sampling speeds, adding more synchronous methods (single-ended, differential, both single-shot and continuous), and using bitband for atomic access to the registers so everything is interrupt safe. I won't include methods for analog timers, but there will be examples on how to use IntervalTimer.

  17. #67
    Junior Member
    Join Date
    Jul 2014
    Posts
    9

    Sampling Audio (line/mic)

    What would be a good input circuit to sample line and mic level audio using this library?

  18. #68
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    Sorry I can't give you any information on that, my knowledge of hardware is very limited. Maybe ask in the Audio library thread, where specialist in audio can read it.

  19. #69
    Junior Member
    Join Date
    Jul 2014
    Posts
    8
    Hi Pedvide,


    I think the ADC in teensy3.x is quicker as described, I think about 8 Msps (8bit).

    I tested teensy 3.1 with your library with Sinus-Signal between 20 kHz and about 80 kHz in 8-bit mode. I need for 239 samples ca 41 Ás with one input channel, ca 70Ás with 2 channels . The 8 bit conversion needs for 239 samples (on my GLCD) ca 30 Ás (ca 10 Ás needs the for ... loop) . It's ca 0.126 Ás/samples equal ca 8.5 Msps. I tested it with function micros() (see in the code).

    with these settings in setup:

    // ADC_0 on Pin23 / A9
    adc->setAveraging(1, ADC_0); // set number of averages
    adc->setResolution(8, ADC_0); // set bits of resolution
    adc->setConversionSpeed(ADC_VERY_HIGH_SPEED,ADC_0); // change the conversion speed
    adc->setSamplingSpeed(ADC_VERY_HIGH_SPEED,ADC_0); // change the sampling speed

    // ADC_1 on Pin16 / A2
    adc->setAveraging(1, ADC_1); // set number of averages
    adc->setResolution(8, ADC_1); // set bits of resolution
    adc->setConversionSpeed(ADC_VERY_HIGH_SPEED, ADC_1); // change the conversion speed
    adc->setSamplingSpeed(ADC_VERY_HIGH_SPEED, ADC_1); // change the sampling speed

    adc->startContinuous(readPin0, ADC_0);
    adc->startContinuous(readPin1, ADC_1);

    ...

    and in the loop - section:


    ...
    ms = micros();
    uint8_t xpom = 240; // max x counts on the Display (2.2 ")
    for(uint8_t xpo=0; xpo < xpom; xpo++) {

    SampleC[xpo] = adc->analogReadContinuous(ADC_0);// read a new value, will return ADC_ERROR_VALUE if the comparison is false.

    SampleD[xpo] = 20 + adc->analogReadContinuous(ADC_1); // <<<<<<<<<<<<<<<<<<<<<<<<<<
    // the addition of 20 is to show the two equal-signals (I have only one signal-source) on different points on the display
    }

    ms = micros() - ms;


    mausi_mick
    Last edited by mausi_mick; 07-29-2014 at 06:44 AM.

  20. #70
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    analogReadContinuous will always return a value, but it doesn't mean it's a new one. I imagine you are getting a number of duplicate values. The speed you are measuring is the speed at which the loop function executes!
    The best thing with continuous functions is to use interrupts, otherwise you can use bool isComplete(adc_num).

  21. #71
    Junior Member
    Join Date
    Jul 2014
    Posts
    8
    Thanks for your information.
    But I think it's , I need it for a small display, there it is not so critical with 7 or 8 bit resolution.
    I tested it with function : isComplete(), but the conversion is more than 4 times slower.


    T
    Last edited by mausi_mick; 07-30-2014 at 06:25 AM.

  22. #72
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    If it works for you then use it, of course. But don't think that you are actually measuring a new value every 0.126 us! The fastest you can measure new values is 1262 kHz, or 0.79 us, and that's using settings that are out of specs.

  23. #73
    where can the library be found?

  24. #74
    Senior Member
    Join Date
    Jul 2013
    Posts
    272
    See the first post for the link and more information.

  25. #75
    Why do the ADC read methods return signed int values?

    --Edit--
    Oh of course. Error codes.
    Last edited by hoosieree; 08-04-2014 at 08:03 PM.

Posting Permissions

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