Forum Rule: Always post complete source code & details to reproduce any issue!
Page 15 of 25 FirstFirst ... 5 13 14 15 16 17 ... LastLast
Results 351 to 375 of 612

Thread: New I2C library for Teensy3

  1. #351
    For those interested, I have modified Adafruit's BNO055 library to be compatible with I2c_t3.

    Read more about it here.

  2. #352
    Senior Member
    Join Date
    Jan 2013
    Location
    San Francisco Bay Area
    Posts
    638
    Cool, I like the addition of Wire or Wire1 access. I assume it works if you use both Wire & Wire1 concurrently, each with their own sensor. Have you tried it with 2?

  3. #353
    Senior Member
    Join Date
    Nov 2012
    Location
    Salt Lake City, UT, USA
    Posts
    246
    Thanks so much for writing this. I am finally getting around to using it.
    Here is a TMP102 temp sensor library if anyone wants to use it

  4. #354
    Quote Originally Posted by linuxgeek View Post
    Cool, I like the addition of Wire or Wire1 access. I assume it works if you use both Wire & Wire1 concurrently, each with their own sensor. Have you tried it with 2?
    Yes it works.

  5. #355
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Quote Originally Posted by amundsen View Post
    For those interested, I have modified Adafruit's BNO055 library to be compatible with I2c_t3.

    Read more about it here.
    Great, thanks. I've added a link to it on the top post under Compatible Libraries header. I'll also link it on GitHub.

  6. #356
    Junior Member
    Join Date
    Mar 2016
    Posts
    5
    I have a strange problem, which may not be related to the i2c_t3 library, but I hope someone reading this thread can help me.

    The problem is that I get failed calls to endTransmission() and requestFrom() - but only after my code has been running for minutes or even hours. The typical pattern is that I get acknowledge fails periodically, but with increasing frequency. After some hours I finally get timeout on all endTransmission calls.

    I am using a Teensy 3.2 and eight MCP23017 port expanders.

    Any ideas how I2C can become increasingly unstable?

  7. #357
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Quote Originally Posted by tobiasebsen View Post
    I have a strange problem, which may not be related to the i2c_t3 library, but I hope someone reading this thread can help me.

    The problem is that I get failed calls to endTransmission() and requestFrom() - but only after my code has been running for minutes or even hours. The typical pattern is that I get acknowledge fails periodically, but with increasing frequency. After some hours I finally get timeout on all endTransmission calls.

    I am using a Teensy 3.2 and eight MCP23017 port expanders.

    Any ideas how I2C can become increasingly unstable?
    It could be that some of the port expander slaves are dropping clocks and getting out-of-sync or stuck (they may not be getting stuck in a way that completely blocks the bus). Perhaps try pulling some slaves off the bus to see if it is a particular device, or try reducing the clock rate to see if you can improve the data integrity. If it is a noisy environment (bad supply/ground connections, no bypass caps, etc), that could also contribute to traffic errors.

    If basic tweaks don't work then you'll need more detailed diagnosis and error codes to try and figure out why it's failing, eg:
    • always same device fails?
    • same error code?
    • MCP23017 has a reset line. If a fail occurs and you toggle the reset line, does it start working again?


    I would start with the basic stuff, trying to clean up the signaling on the line and reducing speed if necessary. If a scope shows the signals are clean, then maybe check for bad connections or bad slave devices.

    In theory START/STOP signals on the line are supposed to reset Slaves regardless of their state, but having seen the verilog that some people write for these interfaces, and having written interfaces myself I can tell you theory isn't always reality.

  8. #358
    Junior Member
    Join Date
    Mar 2016
    Posts
    5
    Quote Originally Posted by nox771 View Post
    It could be that some of the port expander slaves are dropping clocks and getting out-of-sync or stuck (they may not be getting stuck in a way that completely blocks the bus). Perhaps try pulling some slaves off the bus to see if it is a particular device, or try reducing the clock rate to see if you can improve the data integrity. If it is a noisy environment (bad supply/ground connections, no bypass caps, etc), that could also contribute to traffic errors.

    If basic tweaks don't work then you'll need more detailed diagnosis and error codes to try and figure out why it's failing, eg:
    • always same device fails?
    • same error code?
    • MCP23017 has a reset line. If a fail occurs and you toggle the reset line, does it start working again?


    I would start with the basic stuff, trying to clean up the signaling on the line and reducing speed if necessary. If a scope shows the signals are clean, then maybe check for bad connections or bad slave devices.

    In theory START/STOP signals on the line are supposed to reset Slaves regardless of their state, but having seen the verilog that some people write for these interfaces, and having written interfaces myself I can tell you theory isn't always reality.
    Thanks for the suggestions. I have not had the chance to put a scope on the signal yet, but that would surely get me a better insight on what is going on.

    The thing I don't understand is how the signal can become worse over time and eventually lock up the I2C bus completely. And what is even stranger is that resetting the Teensy actually resolves the lock-up.

  9. #359
    Junior Member
    Join Date
    Mar 2016
    Posts
    5
    Okay, here is what I found out so far:

    1) Unplugging my slave-device seems to lock up the I2C bus in such a way that it cannot recover when I re-connect it.
    2) endTransmission() returns I2C_TIMEOUT because i2c->currentStatus is still I2C_SENDING when finish_() is called.
    3) Looking at my scope, the SCL and SDA pins are stuck in high state.
    4) Calling resetBus() or begin() does not get I2C running again.

    Any ideas what might cause this?

  10. #360
    Is there a way to use a rate less than 100? I have a situation where the capacitance is high enough to disrupt the i2c even at 100. Unfortunately there's no way for me to reduce the capacitance so I just need to find a way to get this working. Thanks

  11. #361
    Senior Member Ben's Avatar
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    401
    Quote Originally Posted by nickexists View Post
    Is there a way to use a rate less than 100? I have a situation where the capacitance is high enough to disrupt the i2c even at 100. Unfortunately there's no way for me to reduce the capacitance so I just need to find a way to get this working. Thanks
    What pullup resistance are you using? I recall T3 has a very strong internal pullup of a few houndred ohms. Have you tried using that? In theory pullups under 1k should cope with line capacitance of up to about 1nF at 100kHz.
    -Ben

  12. #362
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    5,192
    recent thread noted the spec says 35K +/- 20+?% - - - something way too big to be usable - notes I've seen say use external resistors

  13. #363
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Quote Originally Posted by tobiasebsen View Post
    Okay, here is what I found out so far:

    1) Unplugging my slave-device seems to lock up the I2C bus in such a way that it cannot recover when I re-connect it.
    2) endTransmission() returns I2C_TIMEOUT because i2c->currentStatus is still I2C_SENDING when finish_() is called.
    3) Looking at my scope, the SCL and SDA pins are stuck in high state.
    4) Calling resetBus() or begin() does not get I2C running again.

    Any ideas what might cause this?
    This is quite strange. Normally if the bus is stuck it is stuck low because some slave is holding a signal low. This plus your comment about resetting the T3 master making things work makes me wonder about the T3 device. Have you tried swapping in a different T3? I'll think about this but I'm really not sure what is going on.

    One possibility might be something interfering with the interrupt being serviced. Have you tried running in immediate mode (non-interrupt), eg. using I2C_OP_MODE_IMM in the begin() call or by calling Wire.setOpMode(I2C_OP_MODE_IMM); (can add that line right after begin() when bus is idle). Check and see if that changes anything.

  14. #364
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Quote Originally Posted by nickexists View Post
    Is there a way to use a rate less than 100? I have a situation where the capacitance is high enough to disrupt the i2c even at 100. Unfortunately there's no way for me to reduce the capacitance so I just need to find a way to get this working. Thanks
    There is a way to run at lower rates, but it is not builtin to the library, so it requires some low-level register adjustments. If you look in the setRate_() function there are lines like this:
    Code:
            case I2C_RATE_100:  *(i2c->F) = 0x2C; break;   // 100k    576 (actual 104k)
            case I2C_RATE_200:  *(i2c->F) = 0x24; break;   // 200k    288 (actual 208k)
    Those lines are setting the I2C divider ratio. You can adjust I2C0_F (or I2C1_F if you use Wire1), to alter the divide ratio.

    If you look in the manual here:
    http://pjrc.com/teensy/K20P64M72SF1RM.pdf

    On page 1173 you will see the clockrate setting, and on pages 1187-1188 you will see the divider table. Basically knowing your bus freq, you pick a divide value to get you the rate you want and put that setting into I2C0_F. I would run the begin() call with the 100kHz rate setup, then modify the value directly:
    Code:
    I2C0_F = 0xYY;
    where YY is your byte value determined from the table and register definition.

  15. #365
    Junior Member
    Join Date
    Jun 2016
    Posts
    2
    Quote Originally Posted by tobiasebsen View Post
    1) Unplugging my slave-device seems to lock up the I2C bus in such a way that it cannot recover when I re-connect it.
    2) endTransmission() returns I2C_TIMEOUT because i2c->currentStatus is still I2C_SENDING when finish_() is called.
    3) Looking at my scope, the SCL and SDA pins are stuck in high state.
    4) Calling resetBus() or begin() does not get I2C running again.
    I've been noticing a very similar behavior with a project I'm working on. I've noticed it during both un/re-plugging slave devices (occasionally, not always) as well as randomly occurring during normal operations (usually between 2 seconds to an hour after power-on), but only when I have more than about 4 slaves connected. Both SDA and SCL lines stay high, no output from the Teensy. The functions resetBus() and begin() have no effect, and don't transmit even when called multiple times in a error catching function. The only thing besides power-cycling that I've found to clear this situation is to manually pull SCL low briefly (manually with a jumper).

    Quote Originally Posted by nox771
    Have you tried swapping in a different T3?
    I've seen this with 3 different T3.2 units

    Quote Originally Posted by nox771
    One possibility might be something interfering with the interrupt being serviced. Have you tried running in immediate mode (non-interrupt), eg. using I2C_OP_MODE_IMM in the begin() call or by calling Wire.setOpMode(I2C_OP_MODE_IMM); (can add that line right after begin() when bus is idle). Check and see if that changes anything.
    I've tried running using I2C_OP_MODE_IMM and the entire Teensy then locks up.

    I've been running the I2C at 100kHz, the T3.2 at 24MHz (optimized), have 2K2 pullups from the T3.2 3V3 output, and <200pF I2C bus. Scope traces of both SDA and SCL look clean. Besides i2c_t3 I'm also using 3 of the serial ports, one of which has 1Hz GPS NMEA coming into TinyGPS++, and TaskScheduler. Nothing that I know would have conflicting interrupts.

    Note: I bumped the I2C rate up to 400kHz and haven't been able to duplicate the issue yet in the past hour. But with so little testing I don't want to claim that fixed it.

    Edit: Forgot, the SPI library is also used for logging to an SD card.
    Last edited by j_smith; 06-11-2016 at 12:34 AM.

  16. #366
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Quote Originally Posted by j_smith View Post
    I've been noticing a very similar behavior with a project I'm working on. I've noticed it during both un/re-plugging slave devices (occasionally, not always) as well as randomly occurring during normal operations (usually between 2 seconds to an hour after power-on), but only when I have more than about 4 slaves connected. Both SDA and SCL lines stay high, no output from the Teensy. The functions resetBus() and begin() have no effect, and don't transmit even when called multiple times in a error catching function. The only thing besides power-cycling that I've found to clear this situation is to manually pull SCL low briefly (manually with a jumper).

    I've seen this with 3 different T3.2 units

    I've tried running using I2C_OP_MODE_IMM and the entire Teensy then locks up.
    This is all really strange. Slow-degredation could be caused by things like memory leaks on the software side, or temperature on the hardware side. I'm not sure about something like temp, but given the historical use of the library I think something like a memory leak would have shown up by now.

    I think the common factor here is the heavy loading on the I2C bus. I'm wondering if the peripheral has trouble with slow-rise signals. I've worked on the hardware side of these interfaces before and there can be all manner of circuits used from very simple to excessively complex. Sometimes designers redesign everything and sometimes they use "off-the-shelf" blocks (either way could be potentially error prone). Even though I2C is only a 2 wire bus, there is an implicit conversion from analog to digital, and various methods of setting A/D switch points (eg. fixed ground referenced, mid-level based on input swing, mid-level based on supply, etc...). It's possible slow-rise signals are messing with the hardware side peripheral logic (given the rather poor state of the internal pullup design for I2C on these parts, this would not be surprising to me at all).

    A suggestion I have would be to speedup the rise-time on the bus. Cut the pullup resistance way down to get the edge rates up and see if there is any effect. I'm really not sure what else might be going on, I'll think about it some more.

  17. #367
    Can someone please give me a bit of guidance, as I am struggling to get this working correctly.

    The plan is to have a TeensyLC driving some WS2812 LEDS, this will be connected to a Raspberry PI 3, which is hosting a web server and will allow me to change the LED sequence/colors. The idea was to use I2C to communicate between the TeensyLC and PI, with the PI as the master ans TeensyLC as the slave.

    Everything works, until I add another I2C device and then things get weird. When I write to the other I2C device (in this example a Teensy3) I receive data on the TeensyLC. The sample code blow is supposed to send "Hello TeensyLC" followed by a random number. Here's what I get when I run it...

    Code:
    Hello TeensyLC571
    Hello TeensyLC5711
    Hello TeensyLC57111
    Hello TeensyLC571111
    Hello TeensyLC5711111
    Hello TeensyLC57111111
    Hello TeensyLC833
    Hello TeensyLC8333
    Hello TeensyLC83333
    Hello TeensyLC833333
    Hello TeensyLC8333333
    Hello TeensyLC83333333
    Hello TeensyLC474
    Hello TeensyLC4744
    Hello TeensyLC47444
    Hello TeensyLC474444
    Hello TeensyLC4744444
    Hello TeensyLC986
    Hello TeensyLC9866
    Hello TeensyLC98666
    Hello TeensyLC986666
    Hello TeensyLC9866666
    Hello TeensyLC98666666
    Every time it writes to the Teensy3, I am getting a repeat of the TeensyLC data + the last character repeated. I am sure I am just being stupid and missing the obvious, so please put me out of my misery.

    EDIT: I just hooked up the Teesny3 to another PC so I could debug it's output at the same time using the code below and it is printing as expected.


    The Teesny3 is running the slave example code and the TeensyLC is running the slightly modified code below ...
    Code:
    #include <i2c_t3.h>
    
    // Function prototypes
    void receiveEvent(size_t len);
    
    //
    // Setup
    //
    void setup()
    {
        pinMode(LED_BUILTIN,OUTPUT); // LED
    
        // Setup for Slave mode, address 0x66, pins 18/19, external pullups, 400kHz
        Wire.begin(I2C_SLAVE, 0x66, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
    
        // register event
        Wire.onReceive(receiveEvent);
    
        Serial.begin(9600);
    }
    
    void loop()
    {
        digitalWrite(LED_BUILTIN,HIGH); // double pulse LED while waiting for I2C requests
        delay(10);                      // if the LED stops the slave is probably stuck in an ISR
        digitalWrite(LED_BUILTIN,LOW);
        delay(100);
        digitalWrite(LED_BUILTIN,HIGH);
        delay(10);
        digitalWrite(LED_BUILTIN,LOW);
        delay(880);
    }
    
    //
    // handle Rx Event (incoming I2C request/data)
    //
    void receiveEvent(size_t len)
    {
        while(Wire.available())
        {
          char c = Wire.read();     // receive byte as a character
        }
        Serial.println();           // print newline
    }
    The PI is running Windows IoT and here's the code for it...
    Code:
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    using Windows.Devices.Enumeration;
    using Rinsen.IoT.OneWire;
    using Windows.Devices.I2c;
    using System.Diagnostics;
    using System.Threading;
    
    namespace App1
    {
        public sealed partial class MainPage : Page
        {
            // teensy vars
            private I2cDevice _teensyLC;
            private Timer _teensyLCTimer;
            private I2cDevice _teensy3;
            private Timer _teensy3Timer;
    
            public MainPage()
            {
                this.InitializeComponent();
                initTeensy();
            }
    
            private async void initTeensy()
            {
                var settings = new I2cConnectionSettings(0x66); // teensylc address
                settings.BusSpeed = I2cBusSpeed.FastMode;
                string aqs = I2cDevice.GetDeviceSelector("I2C1");
                var dis = await DeviceInformation.FindAllAsync(aqs);
                _teensyLC = await I2cDevice.FromIdAsync(dis[0].Id, settings);
                _teensyLCTimer = new Timer(this.TeensyLCTimerCallback, null, 0, 1000);
                // teensy 3
                settings = new I2cConnectionSettings(0x44); // teensy3 address
                settings.BusSpeed = I2cBusSpeed.FastMode;
                aqs = I2cDevice.GetDeviceSelector("I2C1");
                dis = await DeviceInformation.FindAllAsync(aqs);
                _teensy3 = await I2cDevice.FromIdAsync(dis[0].Id, settings);
                _teensy3Timer = new Timer(this.Teensy3TimerCallback, null, 0, 200);
            }
    
            private void TeensyLCTimerCallback(object state)
            {
                byte[] writeBuff = new byte[6];
                try
                {
                    string msg = "Hello TeensyLC" + new Random().Next(999).ToString();
                    byte[] sendBuff = new byte[msg.Length];
                    sendBuff = System.Text.Encoding.UTF8.GetBytes(msg);
                    _teensyLC.Write(sendBuff);
                    Debug.Write("TeensyLC message sent [" + msg + "]\r\n");
                }
                catch (Exception f)
                {
                    Debug.WriteLine(f.Message);
                }
            }
    
            private void Teensy3TimerCallback(object state)
            {
                byte[] writeBuff = new byte[6];
                try
                {
                    string msg = "Hello Teensy3" + new Random().Next(999).ToString();
                    byte[] sendBuff = new byte[msg.Length];
                    sendBuff = System.Text.Encoding.UTF8.GetBytes(msg);
                    _teensy3.Write(sendBuff);
                    Debug.Write("Teensy3 message sent [" + msg + "]\r\n");
                }
                catch (Exception f)
                {
                    Debug.WriteLine(f.Message);
                }
            }
        }
    }
    TIA.

    Les
    Last edited by Pointy; 07-01-2016 at 04:18 PM.

  18. #368
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Quote Originally Posted by Pointy View Post
    The Teesny3 is running the slave example code and the TeensyLC is running the slightly modified code below ...
    Code:
    //
    // handle Rx Event (incoming I2C request/data)
    //
    void receiveEvent(size_t len)
    {
        while(Wire.available())
        {
          char c = Wire.read();     // receive byte as a character
        }
        Serial.println();           // print newline
    }
    You must have some other kind of receive function. This doesn't seem to do anything at all. It reads a byte into the same local-scope "c" var, over and over, then dumps it when it exits scope and then prints a newline.

    The original Slave example is only designed to work with the original Master example - it is using a protocol layer on top of base I2C communication (it has a command and address byte as part of the data payload). Your PI master is not going to be talking to it the right way.

    I would start by taking a closer look at the T3 and LC receiveEvent() functions. I would not run two Slaves until you get one working exactly right. If you have trouble with that, post just that one with details of the problem.

  19. #369
    Quote Originally Posted by nox771 View Post
    You must have some other kind of receive function. This doesn't seem to do anything at all. It reads a byte into the same local-scope "c" var, over and over, then dumps it when it exits scope and then prints a newline.

    The original Slave example is only designed to work with the original Master example - it is using a protocol layer on top of base I2C communication (it has a command and address byte as part of the data payload). Your PI master is not going to be talking to it the right way.

    I would start by taking a closer look at the T3 and LC receiveEvent() functions. I would not run two Slaves until you get one working exactly right. If you have trouble with that, post just that one with details of the problem.
    Thanks for the reply, and sorry somehow I messed up the code, it should be...

    Code:
    void receiveEvent(size_t len)
    {
        while(Wire.available())
        {
          char c = Wire.read();     // receive byte as a character
          Serial.print(c);          // print the character
        }
        Serial.println();           // print newline
    }
    I realise the original slave code was designed to work with the master which is why I modified it. (The PI code is just sending a string for this simple test and works fine with a single TeensyLC device) The point is that this code works perfectly when I swap out the TeensyLC with a Teensy3. Why? (something to do with the STOP signal?)

    The original project is using a DS2482-100 with a DS18B20 thermal sensor and the Rinsen OneWire library, when I added the TeensyLC, I ran into the problems described above, where every time the sensor was read I would receive data on the TeensyLC. To help troubleshoot the issue I created a new project without the DS2482, substituting it with a Teensy3 and still I have the same issues. However the same code running on a Teensy3, in the original project works fine with the DS2482.

    Hope this makes sense.

    Regards,

    Les

  20. #370
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Quote Originally Posted by Pointy View Post
    [/CODE]
    I realise the original slave code was designed to work with the master which is why I modified it. (The PI code is just sending a string for this simple test and works fine with a single TeensyLC device) The point is that this code works perfectly when I swap out the TeensyLC with a Teensy3. Why? (something to do with the STOP signal?)

    The original project is using a DS2482-100 with a DS18B20 thermal sensor and the Rinsen OneWire library, when I added the TeensyLC, I ran into the problems described above, where every time the sensor was read I would receive data on the TeensyLC. To help troubleshoot the issue I created a new project without the DS2482, substituting it with a Teensy3 and still I have the same issues. However the same code running on a Teensy3, in the original project works fine with the DS2482.
    The STOP method on T3 and LC is different, wherein LC is using a STOP interrupt (a newer development) and T3 is using a pin hack (but one that has been running quite well for a long time), so it is possible there is something going on there.

    Overall I'm still not getting a complete picture of what's going on here. As I understand it, talking to either the T3 or LC slaves individually if only one is connected to the bus works fine, is that right? These are running a basic Slave that reads the data and prints it, that's all right? No other blocking interrupts or other wierdness in parallel?

    This may not be on the Slave side. One thing that I see is that these timers look like an integer multiple of each other:
    Code:
    _teensyLCTimer = new Timer(this.TeensyLCTimerCallback, null, 0, 1000);
    _teensy3Timer = new Timer(this.Teensy3TimerCallback, null, 0, 200);
    I don't know if they step on each other, or if it's right or wrong (I'm unfamiliar with this code), but it seems something could be colliding if these are sharing an interface. Is it possible to use one timer and ping-pong the messages between Slaves? That would eliminate some concerns if things aren't thread safe and they collide.

    Ideally a logic analyzer shot of traffic right when the problem occurs would help, but I'm guessing that's a difficult thing.

  21. #371
    Quote Originally Posted by nox771 View Post
    Overall I'm still not getting a complete picture of what's going on here.
    It's actually hard to explain without seeing it in action. (It took me a whole day to get this far and creating the new project helped me see whats going on, all though I have no idea why.)

    Quote Originally Posted by nox771 View Post
    As I understand it, talking to either the T3 or LC slaves individually if only one is connected to the bus works fine, is that right? These are running a basic Slave that reads the data and prints it, that's all right? No other blocking interrupts or other wierdness in parallel?
    Correct. In the PI code, if I comment out the Teensy3 timer, this is the output I get on the LC...

    Code:
    Hello TeensyLC551
    Hello TeensyLC97
    Hello TeensyLC881
    Hello TeensyLC307
    Hello TeensyLC568
    Hello TeensyLC993
    Hello TeensyLC777
    Hello TeensyLC562
    Hello TeensyLC986
    Hello TeensyLC412
    Hello TeensyLC837
    Hello TeensyLC263
    Hello TeensyLC525
    Now if I stop the PI code and comment out the LC timer, this is what I get...

    Code:
    Hello TeensyLC5255
    Hello TeensyLC52555
    Hello TeensyLC525555
    Hello TeensyLC5255555
    Hello TeensyLC52555555
    Hello TeensyLC525555555
    Hello TeensyLC5255555555
    Hello TeensyLC52555555555
    Hello TeensyLC525555555555
    Hello TeensyLC5255555555555
    Hello TeensyLC52555555555555
    Hello TeensyLC525555555555555
    Hello TeensyLC5255555555555555
    Hello TeensyLC52555555555555555
    Hello TeensyLC525555555555555555
    Hello TeensyLC5255555555555555555
    Hello TeensyLC52555555555555555555
    Hello TeensyLC525555555555555555555
    Hello TeensyLC5255555555555555555555
    Hello TeensyLC52555555555555555555555
    Hello TeensyLC525555555555555555555555
    Hello TeensyLC5255555555555555555555555
    Hello TeensyLC52555555555555555555555555
    Hello TeensyLC525555555555555555555555555
    Hello TeensyLC5255555555555555555555555555
    Hello TeensyLC52555555555555555555555555555
    Hello TeensyLC525555555555555555555555555555
    Hello TeensyLC5255555555555555555555555555555
    Hello TeensyLC52555555555555555555555555555555
    The last block of data is being received and the 'Wire.available()' is growing by one byte each time something is sent to the Teensy3. (or another device on the bus) If I reboot the LC, it receives nothing, it only happens if at least one block of data has already been sent.

    Quote Originally Posted by nox771 View Post
    I don't know if they step on each other, or if it's right or wrong (I'm unfamiliar with this code), but it seems something could be colliding if these are sharing an interface. Is it possible to use one timer and ping-pong the messages between Slaves? That would eliminate some concerns if things aren't thread safe and they collide.
    I just made the Teensy3 timer much shorter to try and illustrate what's going on, I don't think they ever actually run at exactly the same time.(I am sure I would get exception when writing to the device if there was a sharing violation)

    Regards,

    Les

  22. #372
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Ok I get it, your saying the T3 traffic is re-triggering the LC receiveEvent, which somehow is probably reprinting the last character in the buffer. I'll have to see if I can rig a local test case. I'm in the middle of the library update for 3.5, but I'll see if I can work it in.

  23. #373
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    406
    Actually I'm wondering if this is due to interaction with Serial. For Serial to function there is implicit ISR traffic due to USB (USB runs at a higher priority). receiveEvent() is a callback from inside the I2C ISR, so it's really part of the ISR. Stacking ISRs works due to the NVIC, but one thing you can try is to pull the Serial stuff out of receiveEvent(). The way the code is written compounds this effect due to the way it is written - printing one byte at a time, versus printing a whole buffer. Since I2C is slow this creates a lot of dragged out USB traffic.

    To fix that here is something to try - use receiveEvent() to stuff the data in a buffer, and then set a flag. Mark the flag as volatile. In your main loop check for the flag, and if it occurs print the buffer then clear the flag.

  24. #374
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    5,192
    When the ReceiveEvent is called :: void receiveEvent(size_t len)

    The number of known bytes available is provided. There may be a problem - and this may just hide the symptom, but what do you get with:

    Code:
    void receiveEvent(size_t len)
    {
        for ( size_t ii=0; ii<len; ii++)
        {
          char c = Wire.read();     // receive byte as a character
          Serial.print(c);          // print the character
        }
        Serial.println();           // print newline
    }
    If this works then this message all the next messages should arrive and be handled properly. If the chatter persists that may help clarify the problem.
    Last edited by defragster; 07-02-2016 at 09:48 AM.

  25. #375
    Quote Originally Posted by defragster View Post
    When the ReceiveEvent is called :: void receiveEvent(size_t len)

    The number of known bytes available is provided. There may be a problem - and this may just hide the symptom, but what do you get with:

    Code:
    void receiveEvent(size_t len)
    {
        for ( size_t ii=0; ii<len; ii++)
        {
          char c = Wire.read();     // receive byte as a character
          Serial.print(c);          // print the character
        }
        Serial.println();           // print newline
    }
    If this works then this message all the next messages should arrive and be handled properly. If the chatter persists that may help clarify the problem.
    Thanks for the suggestion but it makes no difference.

    Quote Originally Posted by nox771 View Post
    Actually I'm wondering if this is due to interaction with Serial. For Serial to function there is implicit ISR traffic due to USB (USB runs at a higher priority). receiveEvent() is a callback from inside the I2C ISR, so it's really part of the ISR. Stacking ISRs works due to the NVIC, but one thing you can try is to pull the Serial stuff out of receiveEvent(). The way the code is written compounds this effect due to the way it is written - printing one byte at a time, versus printing a whole buffer. Since I2C is slow this creates a lot of dragged out USB traffic.

    To fix that here is something to try - use receiveEvent() to stuff the data in a buffer, and then set a flag. Mark the flag as volatile. In your main loop check for the flag, and if it occurs print the buffer then clear the flag.
    I though this had made a difference until I removed the LED flash from the main loop.

    First off I tweaked the PI code to print a counter, rather than a random number and this is the expected output...

    Code:
    Hello TeensyLC [0]
    Hello TeensyLC [1]
    Hello TeensyLC [2]
    Hello TeensyLC [3]
    Hello TeensyLC [4]
    Hello TeensyLC [5]
    Hello TeensyLC [6]
    Hello TeensyLC [7]
    Hello TeensyLC [8]
    Hello TeensyLC [9]
    Hello TeensyLC [10]
    This is what I am now getting...
    Code:
    Hello TeensyLC [0]
    Hello TeensyLC [0]]
    Hello TeensyLC [0]]]
    Hello TeensyLC [0]]]]
    Hello TeensyLC [0]]]]]
    Hello TeensyLC [1]
    Hello TeensyLC [1]]
    Hello TeensyLC [1]]]
    Hello TeensyLC [1]]]]
    Hello TeensyLC [1]]]]]
    Hello TeensyLC [1]]]]]]
    Hello TeensyLC [2]
    Hello TeensyLC [2]]
    Hello TeensyLC [2]]]
    Hello TeensyLC [2]]]]
    Hello TeensyLC [2]]]]]
    Hello TeensyLC [2]]]]]]
    Hello TeensyLC [3]
    Hello TeensyLC [3]]
    Hello TeensyLC [3]]]
    Hello TeensyLC [3]]]]
    Hello TeensyLC [3]]]]]
    Hello TeensyLC [3]]]]]]
    TeensyLC code...

    Code:
    #include <i2c_t3.h>
    
    // Function prototypes
    void receiveEvent(size_t len);
    
    volatile bool msgRecieved = false;
    char msg[31];
    //
    // Setup
    //
    void setup()
    {
        pinMode(LED_BUILTIN,OUTPUT); // LED
    
        // Setup for Slave mode, address 0x66, pins 18/19, external pullups, 400kHz
        Wire.begin(I2C_SLAVE, 0x66, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
    
        // register event
        Wire.onReceive(receiveEvent);
    
        Serial.begin(9600);
    }
    
    void loop()
    {
        if (msgRecieved)
        {
          Serial.println(msg);
          msgRecieved = false;
        }
    }
    
    //
    // handle Rx Event (incoming I2C request/data)
    //
    void receiveEvent(size_t len)
    {
        memset(msg, 0, sizeof(msg));
        for ( size_t ii=0; ii<len; ii++)
        {
          char c = Wire.read();     // receive byte as a character
          msg[ii] = c;          // add the character
        }
        msgRecieved = true;
    }
    Regards,

    Les

Posting Permissions

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