Forum Rule: Always post complete source code & details to reproduce any issue!
Page 17 of 27 FirstFirst ... 7 15 16 17 18 19 ... LastLast
Results 401 to 425 of 674

Thread: New I2C library for Teensy3

  1. #401
    It seems to be solved!

    As stated above, the change I made is to use the i2c_t3.h library instead of Wire.h and added Wire.setDefaultTimeout(100000); in setup(). A few days ago the uC ran for almost 48 hours and no lock-up/freeze! =) Don't think I have been able to that before. Haven't tried the if(Wire.getError()) error checking function yet, but will give it a try when I have the possibility. Would be nice to have an understanding of if, and how many times, i2c-communication fails.

    @Headroom: Yes, I get your point. The situation is that it's not the end of the world if I loose one or two i2c transmits in an hour. Its compass and wind data that are sent several times per second and then averaged across hundred samples.

    My setup is an sailboat autopilot with i2c-master Teensy 3.2 connected to i2c-slave attiny85 and i2c-slave LSM303 compass. The attiny is connected over a phone cable that is over 15 meter long and in a pretty bad condition. Impressed that it all works so well, especially with the new library. =)

    Thanks a lot for all your input and help!

    Last edited by Tobbera; 08-17-2016 at 09:30 AM.

  2. #402
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    Quote Originally Posted by Tobbera View Post
    It seems to be solved!

    As stated above, the change I made is to use the i2c_t3.h library instead of Wire.h and added Wire.setDefaultTimeout(100000); in setup(). A few days ago the uC ran for almost 48 hours and no lock-up/freeze! =) Don't think I have been able to that before. Haven't tried the if(Wire.getError()) error checking function yet, but will give it a try when I have the possibility. Would be nice to have an understanding of if, and how many times, i2c-communication fails.
    Good to hear that it works!

  3. #403
    Junior Member
    Join Date
    Mar 2015
    Posts
    19
    Hi All,

    I am having a problem with a function I am writing using the i2c_t3 library. I want to read consecutive registers from an i2c device.

    From what I understand, the procedure is to tell the Wire.requestFrom() method that you want two bytes from the initial address. For instance, value_LSB is at address 0x01 and value_MSB is at address 0x02. To then retrieve the value of both registers, we call Wire.requestFrom(value_MSB, 2) and then call Wire.read() twice to read the first and second bytes in the RX buffer.

    Do I have my principle of right, is the first question?

    If I do, the following code is my function:
    Code:
    uint16_t deviceReadBytes(byte deviceAddr, byte regAddr, byte noOfBytes){
      byte data[noOfBytes];
      uint16_t value;
    
      Wire.beginTransmission(deviceAddr);       // Notify i2c which device we want to talk to
      Wire.write(regAddr);                      // Notify i2c which register of the device we want to access
      Wire.endTransmission();                   // End the i2c transmission with the device
      Wire.requestFrom(deviceAddr, noOfBytes);  // Request information from the i2c device
    
      while(!Wire.available()){
        // Waiting for i2c to return a value
      }
    
      // Read multiple bytes
      if (noOfBytes > 1) {
        for (int i = 1 ; i <= noOfBytes ; i++) {
          data[i - 1] = Wire.readByte();        // Write i'th byte to the data array
        }
        value = (data[0] << 8) | data[1];       // Bit shift the first byte and perform a bitwise or operation to combine the MSB & LSB values
      } else {  // Read one byte
        value = Wire.read();                    // Read byte from RX buffer into value
      }
      return value;
    }
    It is designed to read either one address or multiple addresses.

    I do realize that when I say that it is designed for reading multiple address, it can only do two because of the bit shifting and the bitwise operation, but that is not important at this point. I can fix that in the logic later.

    The reason I know there is a problem is that I know the values of two particular registers I am reading. If I read them individually I get the right values, if I read them using the above function I get the incorrect value for the second register.

    Thanks for all and any help in advance.

    Kind regards,

    Dylan

  4. #404
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,431
    I may not be up on the latest c++ stuff, but the one thing that I am not sure of is: byte data[noOfBytes];

    That is to have a variable number of bytes on stack... So the first thing I would try is: maybe define it as data[10];

    And see if your function works any differently.

  5. #405
    Junior Member
    Join Date
    Mar 2015
    Posts
    19
    Hi KurtE,

    Thanks for the response.

    I gave that a whirl and no change unfortunately.

    Kind regards,

    Dylan

  6. #406
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    5,431
    Couple of other things: It would help also if you said something like the two values are: x and y and the return value for reading both was...

    But:

    Quote Originally Posted by Dylan144GT View Post
    For instance, value_LSB is at address 0x01 and value_MSB is at address 0x02. To then retrieve the value of both registers, we call Wire.requestFrom(value_MSB, 2)
    So you are saying the value is stored: LSB, MSB
    But in the code:
    Quote Originally Posted by Dylan144GT View Post

    Code:
    uint16_t deviceReadBytes(byte deviceAddr, byte regAddr, byte noOfBytes){
    ...
        value = (data[0] << 8) | data[1];       // Bit shift the first byte and perform a bitwise or operation to combine the MSB & LSB values
    ...
    It looks like you are processing it like: MSB, LSB

    Also sometimes I casting to make sure things work:
    Might try something like:
    Code:
        value = ((uint16_t)data[1] << 8) | data[0];       // Bit shift the first byte and perform a bitwise or operation to combine the MSB & LSB values

  7. #407
    Junior Member
    Join Date
    Mar 2015
    Posts
    19

    Hi KurtE,

    Many thanks for your help! It was indeed a case of reading the bytes in the incorrect order. The fix was just to change...
    Code:
        ...
        value = (data[0] << 8) | data[1];       // Bit shift the first byte and perform a bitwise or operation to combine the MSB & LSB values
        ...
    to...

    Code:
        ...
        value = (data[1] << 8) | data[0];       // Bit shift the first byte and perform a bitwise or operation to combine the MSB & LSB values
        ...
    Many thanks and much appreciated!

    Kind regards,

    Dylan

  8. #408
    Senior Member
    Join Date
    Feb 2016
    Location
    Australia
    Posts
    219
    where is getClock()?
    Is it possible to get 1.7Mhz on teensy3.2?
    Aiming for 1.2Mhz but debug timing looks like 800k so want getClock to check.
    Last edited by Gibbedy; 09-17-2016 at 03:22 PM.

  9. #409
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    Quote Originally Posted by Gibbedy View Post
    where is getClock()?
    Is it possible to get 1.7Mhz on teensy3.2?
    Aiming for 1.2Mhz but debug timing looks like 800k so want getClock to check.
    Is Wire.getClock() not working?

    In the most recent library it is this inline function (it returns a uint32_t value):
    Code:
        // ------------------------------------------------------------------------------------------------------
        // Get I2C clock - return current clock setting
        // return: uint32_t = bus frequency (Hz)
        // parameters: none
        inline uint32_t getClock(void) { return i2c->currentRate; }
    However you have to understand a few details on the clock system. For the I2C peripheral the theoretical rates and the actual rates are not the same. There are a few effects going on. One is that the peripheral will limit the bit clock (this is just due to internal latencies in the digital implementation of the block at a hardware level), so setting 1.2M may yield an actual 800k bit clock rate. This peripheral limitation is the primary limiter at the high end, and the really high rates give diminishing returns beyond a certain point. Internally the divide ratios are correct, but the external rates will be slower.

    The other effect is due to divide ratios. You can set rates up to 3MHz on T3.2, but at high rates there are fewer divide ratios available so you may not get an exact setting that you want. So for instance there are divide ratios of 20 and 22 IIRC, so on a 60M bus clock using 20 will yield a 3M setting, but 22 will give ~2.73M (a fairly large jump). Essentially the value you set via setClock() is given as a "target" value, and the library will try to choose the closest available divide ratio. The rate you get back from getClock() will be this "quantized" ideal rate (it will not be the true external rate, which is something that would need to be measured via logic analyzer or similar).

    So as an example, setting 2.8M via setClock() may in fact use a divide ratio that gives ~2.7M (depends on bus freq), and then on a logic analyzer the bit clock may come out at a much lower ~1.2M or something like that. There is a throughput plot on the first post and the github page which illustrates the effect.

  10. #410
    Senior Member
    Join Date
    Feb 2016
    Location
    Australia
    Posts
    219
    Oh. I thought getClock() would give me the actual rate, so not much use to me.
    getClock() is not working for me:

    _8x8x8_LED_Cube:115: error: 'class i2c_t3' has no member named 'getClock'
    Serial.println(Wire.getClock());

    I got an 8x8 led cube that was looking a bit seizure inducing running i2c at 400k (730uS to update 5x mcp23017 io expanders)
    Huge improvement with i2c_t3 able to do I believe 800k at 310uS.
    I'm doing 1ms on per layer so i2c is holding me up.

    mcp23017 is good for 1.7Mhz apparently.

  11. #411
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    That doesn't make sense. Make sure you are running the latest library version and it is not linking in an older version from Teensyduino. If you are using a latest library which is in your sketchbook/libraries folder, then it should dump out something like this when it compiles:
    Code:
    Multiple libraries were found for "i2c_t3.h"
     Used: C:\your_sketchbook_folder\libraries\i2c_t3
     Not used: C:\teensyduino_install_folder\arduino-1.6.9\hardware\teensy\avr\libraries\i2c_t3
    If you follow the "used" path, make sure it points to the latest version - near the top of the .cpp or .h file it should say v9:
    Code:
    - (v9) Modified 01Jul16 by Brian (nox771 at gmail.com)
    Or if you have the latest development teensyduino it should be upgraded already. You can find it here:
    https://forum.pjrc.com/threads/36756...ta-4-Available

  12. #412
    Senior Member
    Join Date
    Feb 2016
    Location
    Australia
    Posts
    219
    I'm running v8 so that must be it.

  13. #413
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    921
    Well this is odd, I got some new BNO055 breakout boards from China (my design, should work well, with 4K7 pullups on the board ) and tried one out using a Teensy 3.1 and I can read both of the I2C addresses (BNO055 has one and BMP280 has one), and I get the right WHO_AM_I from all devices and the self checks pass. Then when the sketch goes to read some data, it stalls. This is with i2C_t3 using pins 16/17 like I have done 1 x 10^15 times before. I tried the boards on an STM32L4 and they work fine at 400 kHz. Boards seems OK. Then I tried back on the Teensy at 100 kHz and... works fine. Then I tried at 1000 kHz and... works fine, but 400 kHz, it stalls on the first data read as far as I can tell. I am using Teensiduino v 1.30 I believe and Arduino 1.6.8. Before I spew a lot of code your way, does this seem even possible? I mean, is there some weird RC resonance causing trouble at 400 kHz? Never seen this before...

  14. #414
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    A few recommendations:

    1) Inside the latest version there is an archive folder containing all other versions. I would first try and run v8 release to see if the problem is still there. The code that sets the divider was changed a lot in v9, so it is unlikely but there may be something going on there. Running with v8 would verify it one way or the other.

    2) On v9 code, run Wire.setClock(400000) to set 400kHz, then read the clock setting, eg. uint32_t rate = Wire.getClock(), and print it to see if it is set correctly to 400kHz. If not then post your F_BUS freq and whatever setup code you are running.

    3) To get a more complete picture you could create a loop. First set default timeouts via setDefaultTimeout(), then sweep across freq, say 100kHz to 1M using setClock() and getClock() as above. The timeout should catch the case where it fails. Print the output at each freq.

    I can't say if it is or isn't a HW fault. I haven't seen any other case where it works at higher and lower freq but not in the middle.

  15. #415
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    921
    I am suspecting a hardware issue.

    I went back to v.08 and also could not get it to work at 400 kHz, but it did at 100 kHz and 1000 kHz again. I went back to v.09 and was able to get it to work at 350 (352 kHz) and 450 (461) kHz but not at 390 (400 kHz) or 400 kHz (400kHz) where the frequencies are setClock(getClock). There must be a weird resonance at 400 kHz preventing the device from reading the data registers, meaning reading multiple bytes since I can read the WHO_AM_I registers and self test registers just fine and sometimes I can even get through the accel calibration at 400 kHz before it freezes up (doesn't continue). I'll look into this more tomorrow.

  16. #416
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    2,201
    Quote Originally Posted by onehorse View Post
    I am suspecting a hardware issue.
    Maybe a logic analyzer might help. i've noticed 400khz I2C on T3.5 (381 KHz) isn't the same as on STM32L4 (432 KHz), but actual frequencies aren't that different, so i'd be surprised that a device wouldn't respond.
    Last edited by manitou; 09-20-2016 at 06:56 PM.

  17. #417
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    Quote Originally Posted by onehorse View Post
    I am suspecting a hardware issue.

    I went back to v.08 and also could not get it to work at 400 kHz, but it did at 100 kHz and 1000 kHz again. I went back to v.09 and was able to get it to work at 350 (352 kHz) and 450 (461) kHz but not at 390 (400 kHz) or 400 kHz (400kHz) where the frequencies are setClock(getClock). There must be a weird resonance at 400 kHz preventing the device from reading the data registers, meaning reading multiple bytes since I can read the WHO_AM_I registers and self test registers just fine and sometimes I can even get through the accel calibration at 400 kHz before it freezes up (doesn't continue). I'll look into this more tomorrow.
    This seems like it is just that specific setting causing a problem. What is your F_BUS? Sometimes there are multiple divide settings that are the same divide ratio, but they differ on start/stop timing. It may be this particular setting is not right. Try also changing F_BUS to some other values and see if the problem goes away.

  18. #418
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    921
    Not sure how to check what F_BUS is. It is the default, I mean I do not particularly set it in my code. How can I query the value?

  19. #419
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    3,269
    F_BUS is set in hardware/teensy/avr/cores/teensy3/kinetis.h. But it should be a simple matter to print its value in setup.

  20. #420
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    It is a constant (define), you can just print it. Try this:
    Code:
    Serial.printf("CPU speed is: %d\n",F_CPU);
    Serial.printf("Bus speed is: %d\n",F_BUS);
    For a given F_CPU the F_BUS is setup in the kinetis.h file around line ~750. Path is:
    Code:
    arduino_folder\hardware\teensy\avr\cores\teensy3\kinetis.h
    BTW: to check different F_BUS values, just try compiling with different F_CPU settings.
    Last edited by nox771; 09-22-2016 at 03:57 AM.

  21. #421
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    9,770
    I wrote this to keep an eye on the T_3.5/3.6:
    Code:
    void CPUspecs() {
      Serial.println();
    #if defined(__MKL26Z64__)
      Serial.println( "CPU is T_LC");
    #elif defined(__MK20DX256__)
      Serial.println( "CPU is T_3.1/3.2");
    #elif defined(__MK20DX128__)
      Serial.println( "CPU is T_3.0");
    #elif defined(__MK64FX512__)
      Serial.println( "CPU is T_3.5");
    #elif defined(__MK66FX1M0__)
      Serial.println( "CPU is T_3.6");
    #endif
      Serial.print( "F_CPU =");   Serial.println( F_CPU );
      Serial.print( "ARDUINO =");   Serial.println( ARDUINO );
      Serial.print( "F_PLL =");   Serial.println( F_PLL );
      Serial.print( "F_BUS =");   Serial.println( F_BUS );
      Serial.print( "F_MEM =");   Serial.println( F_MEM );
      Serial.print( "NVIC_NUM_INTERRUPTS =");   Serial.println( NVIC_NUM_INTERRUPTS );
      Serial.print( "DMA_NUM_CHANNELS =");   Serial.println( DMA_NUM_CHANNELS );
      Serial.print( "CORE_NUM_TOTAL_PINS =");   Serial.println( CORE_NUM_TOTAL_PINS );
      Serial.print( "CORE_NUM_DIGITAL =");   Serial.println( CORE_NUM_DIGITAL );
      Serial.print( "CORE_NUM_INTERRUPT =");   Serial.println( CORE_NUM_INTERRUPT );
      Serial.print( "CORE_NUM_ANALOG =");   Serial.println( CORE_NUM_ANALOG );
      Serial.print( "CORE_NUM_PWM =");   Serial.println( CORE_NUM_PWM );
    }
    Last edited by defragster; 09-22-2016 at 06:27 AM.

  22. #422
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    921
    Had my wifi wig out there for a moment...

    The F_BUS is 96 MHz when I set 96 MHz for the CPU speed and 72 MHz when I set the CPU to 72 MHz. Interestingly, when I set the CPU speed to 96 MHz the 400 kHz (400 kHz) I2C setting causes the sensor to stop during the first data reads, but when I set it to 72 MHz CPU speed the 400 kHz (409.09 kHz) I2C bus speed works; the sensor data is read and the device functions normally. Something odd about the 96 Mhz clock speed, I usually don't use it, preferring the 72 MHz. but I guess I got lazy and just kept the default and tripped up on this "feature."

    The above F_BUS values are wrong, this is just the CPU clock speed apparently...

    With 72 MHz CPU setting, 400 kHz I2C clock:

    I2C clock rate = 409090 Hz
    F_CPU =72000000
    ARDUINO =10608
    F_PLL =72000000
    F_BUS =36000000
    F_MEM =24000000
    NVIC_NUM_INTERRUPTS =95
    DMA_NUM_CHANNELS =16
    CORE_NUM_TOTAL_PINS =34
    CORE_NUM_DIGITAL =34
    CORE_NUM_INTERRUPT =34
    CORE_NUM_ANALOG =21
    CORE_NUM_PWM =12

    sensor runs normally.


    with 96 MHz setting, 400 kHz I2C clock:

    I2C clock rate = 400000 Hz
    F_CPU =96000000
    ARDUINO =10608
    F_PLL =96000000
    F_BUS =48000000
    F_MEM =24000000
    NVIC_NUM_INTERRUPTS =95
    DMA_NUM_CHANNELS =16
    CORE_NUM_TOTAL_PINS =34
    CORE_NUM_DIGITAL =34
    CORE_NUM_INTERRUPT =34
    CORE_NUM_ANALOG =21
    CORE_NUM_PWM =12

    sensor freezes.

    with 72 MHz CPU and 300 kHz I2C:

    I2C clock rate = 300000 Hz
    F_CPU =72000000
    ARDUINO =10608
    F_PLL =72000000
    F_BUS =36000000
    F_MEM =24000000
    NVIC_NUM_INTERRUPTS =95
    DMA_NUM_CHANNELS =16
    CORE_NUM_TOTAL_PINS =34
    CORE_NUM_DIGITAL =34
    CORE_NUM_INTERRUPT =34
    CORE_NUM_ANALOG =21
    CORE_NUM_PWM =12


    and the sensor freezes, does not run...
    Last edited by onehorse; 09-22-2016 at 05:57 AM.

  23. #423
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    Quote Originally Posted by defragster View Post
    I wrote this to keep an eye on the T_3.5/3.6:
    Code:
    void CPUspecs() {
      Serial.println();
    #if defined(__MK20DX128__)
      Serial.println( "CPU is T_LC");
    #elif defined(__MK20DX256__)
      Serial.println( "CPU is T_3.1/3.2");
    #elif defined(__MKL26Z64__)
      Serial.println( "CPU is T_3.0");
    #elif defined(__MK64FX512__)
      Serial.println( "CPU is T_3.5");
    #elif defined(__MK66FX1M0__)
      Serial.println( "CPU is T_3.6");
    #endif
      Serial.print( "F_CPU =");   Serial.println( F_CPU );
      Serial.print( "ARDUINO =");   Serial.println( ARDUINO );
      Serial.print( "F_PLL =");   Serial.println( F_PLL );
      Serial.print( "F_BUS =");   Serial.println( F_BUS );
      Serial.print( "F_MEM =");   Serial.println( F_MEM );
      Serial.print( "NVIC_NUM_INTERRUPTS =");   Serial.println( NVIC_NUM_INTERRUPTS );
      Serial.print( "DMA_NUM_CHANNELS =");   Serial.println( DMA_NUM_CHANNELS );
      Serial.print( "CORE_NUM_TOTAL_PINS =");   Serial.println( CORE_NUM_TOTAL_PINS );
      Serial.print( "CORE_NUM_DIGITAL =");   Serial.println( CORE_NUM_DIGITAL );
      Serial.print( "CORE_NUM_INTERRUPT =");   Serial.println( CORE_NUM_INTERRUPT );
      Serial.print( "CORE_NUM_ANALOG =");   Serial.println( CORE_NUM_ANALOG );
      Serial.print( "CORE_NUM_PWM =");   Serial.println( CORE_NUM_PWM );
    }
    That's a good summary. You should post this on the Tips and Tricks thread.

  24. #424
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    425
    Quote Originally Posted by onehorse View Post
    Had my wifi wig out there for a moment...

    The F_BUS is 96 MHz when I set 96 MHz for the CPU speed and 72 MHz when I set the CPU to 72 MHz. Interestingly, when I set the CPU speed to 96 MHz the 400 kHz (400 kHz) I2C setting causes the sensor to stop during the first data reads, but when I set it to 72 MHz CPU speed the 400 kHz (409.09 kHz) I2C bus speed works; the sensor data is read and the device functions normally. Something odd about the 96 Mhz clock speed, I usually don't use it, preferring the 72 MHz. but I guess I got lazy and just kept the default and tripped up on this "feature"
    This isn't right. F_CPU should not equal F_BUS, except maybe 48MHz and below. Default 96MHz F_CPU should be 48MHz F_BUS.

    I'll take a look at the 96MHz F_CPU setting for 400k. A 48MHz F_BUS with 400k I2C is a 120 divide. There are probably multiple ways to set 120, so one of the other settings might work better. I'll try to put together some code for you to test tomorrow.

    Just out of curiosity, can you compile at 72MHz F_CPU with a 300kHz I2C setting and tell me if that works?

  25. #425
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    921
    36 MHz with 300 kHz is also a 120 divide...

Posting Permissions

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