Forum Rule: Always post complete source code & details to reproduce any issue!
Page 27 of 27 FirstFirst ... 17 25 26 27
Results 651 to 665 of 665

Thread: New I2C library for Teensy3

  1. #651
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    423
    Also to anyone following this thread - in regards to Teensy4:

    I was offered a T4 beta board back when it started, but I could not accept as I did not have the requisite time to work on a library port.

    I have now obtained a couple of the retail boards, and although I still lack time, I will probably attempt a port as I can get to it. I have not reviewed Wire code on T4 to know how different it is, but I did read something about it using a FIFO, so my guess is the ISR code would be different enough to warrant a new lib (eg. i2c_t4). I am uncertain of interest level, if any, so any comments would be helpful.

  2. #652
    Senior Member
    Join Date
    Jun 2015
    Posts
    229
    Hi nox771,

    Thanks for getting back on this.

    Before I waste any of your time trying to help me - as I could be trying to achieve the impossible here.
    Would you expect your library to help increase the speed/performance of sending & displaying text to 8 x i2c displays?

    I have now managed to get the "spoof (wire/ic2_t3) " method to compile, but I'm not really seeing much difference performance wise.

    I know there are limitations with this protocol - but not sure what your library is offering versus the std Wire lib.
    As per a post on another thread - I'm seeing a cascading/domino effect when sending the text updates.

    I'm not a software person, so don't really understand most of this stuff.
    Just someone who manages to fumble his way through with the help of forums like this.

    Thanks

  3. #653
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    423
    Quote Originally Posted by bossredman View Post
    Hi nox771,

    Thanks for getting back on this.

    Before I waste any of your time trying to help me - as I could be trying to achieve the impossible here.
    Would you expect your library to help increase the speed/performance of sending & displaying text to 8 x i2c displays?

    I have now managed to get the "spoof (wire/ic2_t3) " method to compile, but I'm not really seeing much difference performance wise.

    I know there are limitations with this protocol - but not sure what your library is offering versus the std Wire lib.
    As per a post on another thread - I'm seeing a cascading/domino effect when sending the text updates.

    I'm not a software person, so don't really understand most of this stuff.
    Just someone who manages to fumble his way through with the help of forums like this.

    Thanks
    It depends. Mostly any speedup will depend on the slave device and if it will respond well to faster than normal I2C speeds. I've gotten faster than normal communication working on something like a SSD1306 I2C display (like the cheap ones on ebay: https://www.ebay.com/sch/i.html?_nkw...06+i2c&_sop=12 ). In that case IIRC it can help with refresh speeds.

    If you are using standard default settings (100kHz/400kHz), then you will likely see the same performance as Wire, as that is what it uses, so it does require specifying something above normal rates.

    Also there are other indirect ways to improve performance. Typical Wire is a blocking interface. Such that the program halts and waits for communication to complete. For i2c_t3 you can background transfers. So in that case you can load the buffer, start the transfer, then continue to a foreground task while it transfers in the background. Most recent releases also support a Master callback that can call a given function when the background transfer completes, so you do not need to monitor it. These are capabilities above and beyond what the standard Wire library will offer. You can check the "basic_master_callback" example for further information on that.

    Note the library linked in post #1 in this thread is obsolete. You should grab the latest one from GitHub (currently v11.0). Due to updated forum rules I can no longer edit the top post to maintain it, so GitHub is the main location now.

  4. #654
    Senior Member
    Join Date
    Jun 2015
    Posts
    229
    Quote Originally Posted by nox771 View Post
    Note the library linked in post #1 in this thread is obsolete. You should grab the latest one from GitHub (currently v11.0). Due to updated forum rules I can no longer edit the top post to maintain it, so GitHub is the main location now.
    Thanks.

    I picked up v11.0 already. It's the only 1 I've tried.

  5. #655
    Senior Member
    Join Date
    Jun 2015
    Posts
    229
    The Digole displays come with their own library for sending data (text, shapes etc) to them.
    So apart from the include for wire.h - all commands for sending the data are Digole specific commands.
    I'm don't directly interact with the Wire libray & commands - I guess that is done indirectly via the Digole Library.

    I just add these statements for each Display & then create an array listing each instance :
    Code:
    DigoleSerialDisp mydisp1(&Wire, '\x27'); 
    DigoleSerialDisp mydisp2(&Wire, '\x28'); 
    ...
    DigoleSerialDisp mydisp8(&Wire, '\x34'); 
    
    mydisp[8] = {mydisp1, mydisp2, ... mydisp8};
    This lets me easily loop each Display & send the data as required.

    Apart from what this statement is actually doing
    Code:
    DigoleSerialDisp mydisp1(&Wire, '\x27');
    I'm able to mostly understand the above.
    But I think I'm just not smart enough to figure out how to make changes to use Master Callbacks etc.

  6. #656
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    423
    Quote Originally Posted by bossredman View Post
    The Digole displays come with their own library for sending data (text, shapes etc) to them.
    So apart from the include for wire.h - all commands for sending the data are Digole specific commands.
    I'm don't directly interact with the Wire libray & commands - I guess that is done indirectly via the Digole Library.
    ...
    You'll have to supply a link to your library you are using. Other than that it is guessing. Using google I can see a DigoleSerial.h lib at:
    https://github.com/phalpern/Thermost...DigoleSerial.h

    That one has a very generic init for I2C config:
    Code:
    _myWire->begin();
    That may be giving you a 100kHz clock, which is standard for Arduino.

    A simple option is to use your init code as-is, then insert a Wire command to adjust the clock:
    Code:
    DigoleSerialDisp mydisp1(&Wire, '\x27'); 
    DigoleSerialDisp mydisp2(&Wire, '\x28'); 
    ...
    DigoleSerialDisp mydisp8(&Wire, '\x34'); 
    Wire.setClock(200000);  // 200kHz
    ...
    ...
    Add that, test it, and see if it works. Then increase it and try again: 400000 = 400kHz, 600000 == 600kHz, 800000 = 800kHz, and so on.

    i2c_t3 lib will quantize the number to the nearest legal value, so you can use any number you like. Most T3 parts can run up to 3000000 = 3MHz. Recent T3.5/3.6 can do higher.

    At some point it will fail and the screen will get garbage or something, then you can back it off.

    Edit: Forgot to mention, high speeds are also limited by the pullup resistor value. If the R-value on the bus is too high the pullups will be slow and it will limit your speeds. Refer to this link:
    http://dsscircuits.com/articles/86-a...l-up-resistors

  7. #657
    Senior Member
    Join Date
    Apr 2013
    Posts
    134
    Hello nox771,

    is it possible to modify/add an modified version of void i2c_t3::resetBus_(struct i2cStruct* i2c, uint8_t bus) to create an clock stretching for slave mode?

  8. #658
    Quote Originally Posted by nox771 View Post
    I am uncertain of interest level, if any, so any comments would be helpful.
    I would definitely be interested.

  9. #659
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    423
    Quote Originally Posted by Markus_L811 View Post
    Hello nox771,
    is it possible to modify/add an modified version of void i2c_t3::resetBus_(struct i2cStruct* i2c, uint8_t bus) to create an clock stretching for slave mode?
    I don't quite follow your question. On Master-side the resetBus function will take I2C off the pins for a moment, manually send some clocks down SCL to release any stuck slaves, and then reconnect I2C. In this case you are talking about having a slave swap I2C off the pin and then holding SCL low for some time?

    I'm not sure if it would work. It would only be possible between bytes, after bit9 and before bit1. But SCL might go high before the slave could switch to pulling it low (not seamless). If it were embedded in the Slave ISR it might be fast enough. But trying to change I2C pin inside the ISR in order to enable manual control would be quite odd. Hard to say, it would require experimentation.

  10. #660
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    423
    Quote Originally Posted by wcalvert View Post
    I would definitely be interested.
    Thanks for the feedback. I'll probably investigate it, but I have no idea when I could get something out.

  11. #661
    Senior Member
    Join Date
    Apr 2013
    Posts
    134
    Quote Originally Posted by nox771 View Post
    In this case you are talking about having a slave swap I2C off the pin and then holding SCL low for some time?

    I'm not sure if it would work. It would only be possible between bytes, after bit9 and before bit1. But SCL might go high before the slave could switch to pulling it low (not seamless). If it were embedded in the Slave ISR it might be fast enough. But trying to change I2C pin inside the ISR in order to enable manual control would be quite odd. Hard to say, it would require experimentation.
    Click image for larger version. 

Name:	i2c_clock_stretching.png 
Views:	1 
Size:	8.7 KB 
ID:	17262

    Yes this was what I have in mind

  12. #662
    Senior Member
    Join Date
    Apr 2013
    Posts
    134
    Looks like an can't edit my post.

    Technically the picture is wrong, after IC-bus specification and user manual Rev. 6

    3.1.9 Clock stretching
    Clock stretching pauses a transaction by holding the SCL line LOW. The transaction
    cannot continue until the line is released HIGH again. Clock stretching is optional and in
    fact, most slave devices do not include an SCL driver so they are unable to stretch the
    clock.
    On the byte level, a device may be able to receive bytes of data at a fast rate, but needs
    more time to store a received byte or prepare another byte to be transmitted. Slaves can
    then hold the SCL line LOW after reception and acknowledgment of a byte
    to force the
    master into a wait state until the slave is ready for the next byte transfer in a type of
    handshake procedure.
    On the bit level, a device such as a microcontroller with or without limited hardware for the
    I2C-bus, can slow down the bus clock by extending each clock LOW period. The speed of
    any master is adapted to the internal operating rate of this device.
    In Hs-mode, this handshake feature can only be used on byte level.

    So after the ACK the Slave can hold the SCL line LOW, I was thinking about this:

    Code:
    void i2c_t3::stretchClock_(struct i2cStruct* i2c, uint8_t bus)
    {
        uint8_t scl = i2c->currentSCL;
        uint8_t sda = i2c->currentSDA;
    
        // change pin mux to digital I/O
        pinMode(sda,((i2c->currentPullup == I2C_PULLUP_EXT) ? INPUT : INPUT_PULLUP));
        digitalWrite(scl,LOW);
        pinMode(scl,OUTPUT);
    
        //Do what ever I want inside the sketch and after it go back in IC Mode
    
        // reconfigure pins for I2C
        pinConfigure_(i2c, bus, scl, sda, i2c->currentPullup, 0, 0);
    
        // reset config and status
        if(*(i2c->S) & 0x7F) // reset config if any residual status bits are set
        {
            *(i2c->C1) = 0x00; // disable I2C, intr disabled
            delayMicroseconds(5);
            *(i2c->C1) = I2C_C1_IICEN; // enable I2C, intr disabled, Rx mode
            delayMicroseconds(5);
        }
        i2c->currentStatus = I2C_WAITING;
    }

  13. #663
    Senior Member
    Join Date
    Jun 2015
    Posts
    229
    Quote Originally Posted by nox771 View Post
    You'll have to supply a link to your library you are using. Other than that it is guessing. Using google I can see a DigoleSerial.h lib at:
    http://"https://github.com/phalpern/...igoleSerial.h"
    Hi sorry for slow response.
    Believe I got the library from here:
    https://www.digole.com/forum.php?topicID=1

    I had already tried various values for Wire.setClock - nothing seemed to make a difference - to the naked eye at least.

    Edit: Forgot to mention, high speeds are also limited by the pullup resistor value. If the R-value on the bus is too high the pullups will be slow and it will limit your speeds. Refer to this link:
    http://dsscircuits.com/articles/86-a...l-up-resistors
    Tried both 4k7 & 2k7 so far - again no noticeable difference.

    The only thing I have seen make a slight difference was changing the Font.
    The displays come with 4 "built-in" fonts but I been using a custom Font (Bold) which can be written direct to the display.
    Flipping back one the std fonts seemed to improve things a touch

  14. #664
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    423
    Quote Originally Posted by Markus_L811 View Post
    So after the ACK the Slave can hold the SCL line LOW, I was thinking about this:

    Code:
    void i2c_t3::stretchClock_(struct i2cStruct* i2c, uint8_t bus)
    {
        uint8_t scl = i2c->currentSCL;
        uint8_t sda = i2c->currentSDA;
    
        // change pin mux to digital I/O
        pinMode(sda,((i2c->currentPullup == I2C_PULLUP_EXT) ? INPUT : INPUT_PULLUP));
        digitalWrite(scl,LOW);
        pinMode(scl,OUTPUT);
    
        //Do what ever I want inside the sketch and after it go back in IC Mode
    
        // reconfigure pins for I2C
        pinConfigure_(i2c, bus, scl, sda, i2c->currentPullup, 0, 0);
    
        // reset config and status
        if(*(i2c->S) & 0x7F) // reset config if any residual status bits are set
        {
            *(i2c->C1) = 0x00; // disable I2C, intr disabled
            delayMicroseconds(5);
            *(i2c->C1) = I2C_C1_IICEN; // enable I2C, intr disabled, Rx mode
            delayMicroseconds(5);
        }
        i2c->currentStatus = I2C_WAITING;
    }
    It's an interesting idea, but I suspect it is a bit more complex than it seems. On the Slave end, the code would run as part of the ISR. The code you show has elements that seem right, but overall it seems off. It would need to work similar to the onReceive() callback.

    In a generic sense it would be more like a per-byte callback, as opposed to onReceive(), which is an end-of-message callback. But the experimental/weird part is that IIRC there is no mechanism to force pin state on the I2C peripheral (I might be wrong, its been a long time since I read the docs). So that only leaves doing the pinConfigure swap as you show, which might work, as long as the I2C bus doesn't change its state while the peripheral is disconnected, and it otherwise remains oblivious to the pin change.

    I'll think about it, but it will be some time before I could really get into it. If you manage to get something to work then let me know, I would be interested.

  15. #665
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    423
    Quote Originally Posted by bossredman View Post
    Hi sorry for slow response.
    Believe I got the library from here:
    https://www.digole.com/forum.php?topicID=1

    I had already tried various values for Wire.setClock - nothing seemed to make a difference - to the naked eye at least.

    Tried both 4k7 & 2k7 so far - again no noticeable difference.

    The only thing I have seen make a slight difference was changing the Font.
    The displays come with 4 "built-in" fonts but I been using a custom Font (Bold) which can be written direct to the display.
    Flipping back one the std fonts seemed to improve things a touch
    I'm not sure what else to suggest. Other displays I've used generally scale with transmit speed (but they were graphical, so I2C was the bottleneck for moving frame data). Perhaps that display has a processor that controls/limits the speed.

    Another possibility is that the host program is sending at a constant rate - in other words, the data itself is communicated faster, but the frame-to-frame speed is constant. I've seen this situation before, where frames were sent at a fixed rate, and even if the data was faster, the host would just idle until the next frame interval.

Posting Permissions

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