CAN SPI Device and I2C Device Co-Operate on one LoPy?



  • Hello PyCom Fans,

    I'm trying to read values from a TSL2591 Light Sensor on the I2C Bus and display the values on a SSD1306 OLED connected to the SPI bus. They both work fine operating individually but upon initializing the SPI bus the I2C device address is no longer available. They are both sharing Lopy P10 / Exp G17 for CLK/SCL which are the default clock signal, and the docs state this clock can be shared. I2C SDA is using P9/G16. SPI MOSI is using P11/G22, MISO is not used. Motoring P10 with my DVM I see that with I2C init the clock is at ~4.0V when idle and clocks between ~3.0V and ~4.0V. With SPI init, P10 goes to 53.0 mV and clocks between ~53mV and ~50mV. I have kept the baud rate the same for both, and and tried different variations of the SPI init parameters to try to keep the clock as same voltage levels. Nothing works that I have tried?

    Is the LoPy designed so that devices can operate on the I2C and SPI together?

    If yes then is this a config issue, user error, or bug?

    Any advice greatly appreciated.

    Following demonstrates how I2C device address disappears after SPI init and I have only been able to recover the I2C address with a hard reboot.

    >>> from machine import SPI, I2C
    >>> i2c = I2C(0, I2C.MASTER, baudrate=100000)
    >>> i2c.scan()
    [40]                                                              #I2C Device address available
    >>> import tsl2591
    >>> tsl = tsl2591.Tsl2591(28)
    >>> full, ir = tsl.get_full_luminosity()
    >>> print(full, ir)
    135 59                                                     #Data read from I2C Light Sensor
    >>> 
    >>> i2c.scan()
    [40]                                                       #I2C Device address still available
    >>> spi = SPI(0, mode=SPI.MASTER, baudrate=100000, polarity=0, phase=0)      #SPI Device init
    >>> i2c.scan()
    []                                                         #I2C Device gone
    >>> i2c = I2C(0, I2C.MASTER, baudrate=100000)              #Init of I2C does not get address back.
    >>> i2c.scan()
    []
    >>> 
    


  • @rdixey

    If you didn't need the speed of SPI, then you could have used I2C (IIC) for both devices (as long as they different addresses), as IIC supports 127 (from memory) device addresses.

    "OLED: https://www.adafruit.com/products/938 #Using as SPI by Default but can be configured for I2C.", rdixey



  • I am coming to the conclusion that LoPy can support either SPI devices or I2C devices but NOT both. Hoping someone from PyCom will provide comment to the users about the intended designed functionality in this regard.

    This is not the case, but I see that:

    Defining the separate I2C SCL at P8 resolved the problem.

    I'm glad that you were able to find the solution :-)

    I jumper the P10/G17 pin to share the clock with the SPI and I2C. Is that a valid use case?

    No, this is not a good idea and it's never going to work. You need to use separate pins for both serial buses.

    So the solution to my post is that I2C and SPI devices CAN both operate on a LoPy however they cannot share the clock signal generated from the default CLK/SCL P10 / Exp G17 signal. There must be a separate clock established for both the SPI bus and the I2C bus.

    That's correct.

    Cheers,
    Daniel



  • @jmarcelino Defining the separate I2C SCL at P8 resolved the problem. With using separate clocks the I2C device address is still available after initializing the SPI Bus.

    So the solution to my post is that I2C and SPI devices CAN both operate on a LoPy however they cannot share the clock signal generated from the default CLK/SCL P10 / Exp G17 signal. There must be a separate clock established for both the SPI bus and the I2C bus.

    I'm moving forward thanks to your and Livius help.

    For comparison to my original post.

    >>> i2c = I2C(0, I2C.MASTER, baudrate=100000,pins=("P9", "P8"))      #I2C initialized
    >>> i2c.scan()
    [40]
    >>> import tsl2591
    >>> tsl = tsl2591.Tsl2591(28)
    >>> full, ir = tsl.get_full_luminosity()
    >>> print(full, ir)
    141 63
    >>> i2c.scan()
    [40]
    >>> spi = SPI(0, mode=SPI.MASTER, baudrate=100000, polarity=0, phase=0)      #SPI initialized
    >>> 
    >>> i2c.scan()                 #I2C address still available and bytes read from it.
    [40]
    >>> full, ir = tsl.get_full_luminosity()
    >>> print(full, ir)
    18 10
    


  • @jmarcelino said in CAN SPI Device and I2C Device Co-Operate on one LoPy?:

    Thank you for tests because i am also interested for future develop.
    An you confirm our thoughts about need to alternate function.



  • @rdixey

    Excellent, you have the voltages under control now!

    I read on the documentation that you set the pins like this:

    i2c.init(mode, *, baudrate=100000, pins=(SDA, SCL))
    

    pins is an optional tuple with the pins to assign to the I2C bus. The default I2C pins are P9 (SDA) and P10 (SCL)

    and actually just tried it myself by moving the I2C CLK pin to P8

    i2c = I2C(0, I2C.MASTER, baudrate=100000,pins=("P9", "P8"))
    

    and happy to report this worked perfectly. Testing with a DS3231 RTC clock over I2C the CLK was now P8.

    So please try to move the I2C CLK somewhere else (maybe P8 as in my example above) and see if works for you.



  • @rdixey
    Good - now you have ok voltage :)
    Will be good to see your connections, unfortunately i have not SPI device.
    All my devices are I2C, digital or analog - and i can not test this myself.
    But as @jmarcelino i do not suppose that this is good idea to share same clock between I2C and SPI. I suppose you should use alternate function.

    But if you show us the wire then maybe we will see something obvious.
    As you say all your devices have builtin pullup then:
    What is voltage when you plug sensor and display?

    • When you only power it up on data lines.
    • And when you start communication?
      I know that without oscilloscope this is hard.

    Will be good if someone with both SPI and I2C devices can join to discussion
    or especially pycom @administrators to show us if you can share that clock.



  • @livius Hi Livius.....per your advice I switched to using the LoPy regulated 3V3 to VIN of my SPI and I2C devices. Doing this reduced the P10/G17 CLK/SCL to 3.284V with clock at idle make it compatible with LoPy. Thanks for starting the discussion on this.

    Unfortunately this did NOT resolve the original problem of my post. The SPI OLED Display works correctly individually. The I2C Light Sensor works correctly individually. But when the SPI is initialized then I2C address becomes unavailable and I have only been able to recover the I2C address through hard reboot.

    I am coming to the conclusion that LoPy can support either SPI devices or I2C devices but NOT both. Hoping someone from PyCom will provide comment to the users about the intended designed functionality in this regard.

    Otherwise I may give up on this adventure and reconfigure the SPI OlED as an I2C device to avoid the problem.



  • @jmarcelino Hi I appreciate your advice. The devices I'm using are breakouts made by Adafruit.
    Light Sensor: https://www.adafruit.com/products/1980 # I2C Only.
    OLED: https://www.adafruit.com/products/938 #Using as SPI by Default but can be configured for I2C.
    Both can accept 5V or 3.3V as VIN. They both have onboard regulators providing 3.3v to the signal pins, and have onboard level shifting. According to their datasheets the I2C bus have onboard pullups installed for SDA/SLC. So I thought that powering as I was doing was valid.

    None the less, your comment about damaging the LoPy made me quickly change to using the LoPy regulated 3.3V pin to power VIN of both devices. Now redoing my same voltage check as before with P10/G17 CLK/SCL signal jumpered to both devices there is 3.284V with clock at Idle making it compatible with LoPy.

    Unfortunately this did not resolve the original problem of my post. The SPI OLED Display works correctly individually. The I2C Light Sensor works correctly individually. But when the SPI is initialized then I2C address becomes unavailable and I have only been able to recover the I2C address through hard reboot.

    • Can you not map the CLK line of either SPI or I2C to a different - separate - pin? I haven't tried it but seems to be one of the initialization options.

    No i did not try to map another pin as SCL yet since I have no docs to refer to as guide. As a test I did try using P5/G12 for the SPI OLED CLK (used by LoRa) and keeping P10/G17 I2C SCL for Light Sensor. I got the same result as stated in my problem. I did not keep it this way since I want to avoid sharing bus / contention with LoRa since this is the key use of a LoPy.

    I am coming to the conclusion that LoPy can support either SPI devices or I2C devices but NOT both. Hoping someone from PyCom will provide comment to the users about the intended designed functionality in this regard.



  • @jmarcelino
    ach - if he use the same power from VIN
    not from 3V3 pin that he has a problem



  • @rdixey said in CAN SPI Device and I2C Device Co-Operate on one LoPy?:

    I'm using GND pin on the Exp Board jumpered to breadboard and Vin pin of exp board jumpered to breadboard for power to both I2C & SPI devices.

    Vin is at 5V (connected directly to USB) so your I2C and SPI devices are being powered by 5V and probably signalling at 5V as well - for example if I2C bus is also connected to those 5V via the pull-up resistors.

    This would explain the high voltages you're seeing - and if so you're probably damaging the LoPy.



  • @livius Hi Livius. I am using a DVM (Digital Volt Meter) to measure the voltage as a simple test. (I don't have an oscilloscope) The power supply to LoPy is USB 3.0 (5V - 5Amp.) LoPy is mounted in the PyCom Expansion board. I'm using GND pin on the Exp Board jumpered to breadboard and Vin pin of exp board jumpered to breadboard for power to both I2C & SPI devices.
    I don't think there is an electrical/power problem. The I2C device works correctly by itself. The SPI device works correctly by itself. The problem is using them at the same time.

    My point for writing about the voltage level of the P10/G17 CLK/SCL signal is that the amplitude of the clock signal is dramatically different (millivolts vs volts) when SPI is initialized compared to when I2C is initialized. Observing that once initialized for SPI (mV range) I cannot reinitialize it back to I2C (V range) without hard reboot.

    Also when the SPI is initialized then I2C address becomes unavailable and I have only been able to recover the I2C address through hard reboot. This does not seem to be an intended functionality.
    My Question is: Is this is a setting issue, a command issue or a bug?

    Also according to the LoPy pinout diagrams, the P10/G17 CLK/SCL is the ONLY configured signal available for clock of I2C & SPI. I am trying to use both and not succeeding.
    My Question is: Does the LoPy only support either I2C OR SPI but NOT BOTH together?



  • What does your I2C bus look like? Where are your pull-ups connected to?

    Maybe I'm missing something but to sharing a single CLK pin between I2C and SPI seems very strange to me, they're very different systems I2C being open drain.

    Can you not map the CLK line of either SPI or I2C to a different - separate - pin? I haven't tried it but seems to be one of the initialisation options.



  • @rdixey
    First how do you measure voltage? Where is your point of electrical ground?
    Because it is strange that you gain 3.853V or 4.016V.
    Maybe i omit something in your description but what tool do you use to measurements?



  • @livius I am powering the LoPy via the USB serial connection to the USB hub built into my LCD monitor. I assumed that would provide adequate power.

    To explain the 4V. - After reboot and I2C init, measuring directly at G17 it is 3.273V, with jumper to the breadboard to provide CLK for the SPI device there is a gain to 3.853V idle clock at that pin on the breadboard. Then adding jumper from that CLK pin on the breadboard over to breadboard for the SCL pin of the I2C device there is a gain to 4.016V idle clock.

    I jumper the P10/G17 pin to share the clock with the SPI and I2C. Is that a valid use case?
    Is this electrically creating a load that is exceeding the tolerance of the GPIO Pin?



  • What do you mean 4V? LoPy is not up 3V3 tolerant.
    and is your power source enough to support all external devices?


Log in to reply
 

Pycom on Twitter