Shop OBEX P1 Docs P2 Docs Learn Events
I2C Beginner Problems — Parallax Forums

I2C Beginner Problems

PiJayPiJay Posts: 5
edited 2022-12-22 14:23 in PASM/Spin (P1)

Dear Folk,

I Try to get running a Comunication between a Propeller Quickstart Board with an Switching Mode Power Supply (SMPS) via I2C.

I am not anprofessional programmer so these question might be silly or obvious to solve.... Sorry for that in adavance.

Setup:
* Cotek AE-800 (Spec. sheet; Comm. Protocol)
* Adress (zero): 1010_000_R/W
* @PSU Connected at pin 19 (SCL) and Pin 20 (SDA) Pullup Resistor to +5V Aux via 2,2kOhm
* @QuickstartBoard SDA Cable to 1 (P0) SCL Cable to Pin 2 (P1) (on 28/29 i got propblems by flashing the board)
* Driver: jm_I2C

Task:
Get the SMPS into I2C Mode. And Setting a Voltage

Due to Com Protocol, I can directly write to the control register (0x7C) then the LED should turn from green to orange.

My first attempt was to Read / Write to Bit 7 of Addres 0x7C [0x7C.7]
So, I took the code of JonnyMc EEProm Demo. and changed a bit:

My Code

CON
  _clkmode = xtal1 + pll16x                                               'Standard clock mode * crystal frequency = 80 MHz
  _xinfreq = 5_000_000

  PSU_SCL =  1     'pin 1   for second SCL  -> EEprom not accacable
  PSU_SDA =  0     'pin 2   for second SDA  -> EEprom not accacable
  PSU_write = $A0 '10100000
  PSU_read = $A1 '10100001
  CLS    = 16                                    ' Parallax Serial Terminal constants
  CR     = 13



VAR
  long  c

OBJ
  i2c      : "jm_i2c"
  pst : "Parallax Serial Terminal"~~~~

PUB main
  pst.Start(115_200)
  pst.Clear

  i2c.setupx(PSU_SCL, PSU_SDA)
  waitcnt(clkfreq/16 + cnt)
  c := 9


  repeat
    c :=  rd_byte($7C)

    pst.Dec(c)
    pst.str(string(CR))

    waitcnt(clkfreq/16 + cnt)


pub rd_byte(address) | value

  i2c.start
  i2c.write($A0)    'adress of the PSU Writing mode
  i2c.write(address)
  i2c.start
  i2c.write($A1)    'adress of the PSU reading mode
  value := i2c.read(i2c#NAK)
  i2c.stop

  return value

pub write_byte(address)
    i2c.start
    i2c.write($A0)    'adress of the PSU Writing mode
    i2c.write(address)
    i2c.write($01)
    i2c.stop~~~~


I never get a feedback to the serial monitor. I found the rd_byte function never gets over I2C.stop, so no Return happens.

i Would apreciate anny Ideas and Help on this issue.

kind regards,
PiJay

*edit: delted nonsens

Comments

  • The Propeller is a 3.3 volts unit and not 5 volts so a pullup to 5 volts is bad.

    I see from the spec that RS232 is available. I would use that as it's a simpler protocol and doesn't require an address to work. You would need to use a resistor to limit the RS232 to 3.3 volts instead of the 5 volts used.

    Also are you connected ground between the two units. That's kind of required.

    Mike

  • Thank you iseries,

    as I understand I would need an additional "CT" board of Cotek. UNfortunately, I have none on stock.

    Using RS232 might be an idea, but I Plan to use some other I2C Sensors as well, so I would prefere to use I2C. But I will try!

    Due to the wiring: is it possible to get kind of the same wiring idea for I2C? Or should i only use 3.3V for the I2C pullup?

    Thanks PiJay

  • JonnyMacJonnyMac Posts: 9,144
    edited 2022-12-22 18:21

    The device may not like the 3.3v levels of the Propeller. Even if you connect the I2C pull-ups to 5v (which should be at least 4.7K if you do), the pin-protection diodes inside the Propeller will clamp the high voltage to about 3.6 volts. That said, you may as well set your I2C bus voltage to 3.3v. If that doesn't work, you'll need to use a bidirectional level-shifter which uses a FET and two resistors. They're very common -- you can even buy them pre-assembled on Amazon.

    https://www.amazon.com/HiLetgo-Channels-Converter-Bi-Directional-3-3V-5V/dp/B07F7W91LC

    I have run 1M baud serial through this device for Dynamixels, so 100kHz I2C won't be a problem -- especially since the Spin-only I2C driver doesn't even run at 100kHz.

    Any time I have a new I2C device I use the attached program to verify that I can reach it. In this image, I have the test I2C bus set to the EEPROM pins, so you can see the response from the EEPROM. If you get a response back you'll learn the actual address of your device. I suspect you may find it at %10101110 ($AE).

    Also are you connected ground between the two units. That's kind of required.

    Good call, Mike -- this is a common error.

  • You might consider making your routines a bit more generic and allow yourself to specific the PSU device address on the I2C bus.

    pub rd_byte(psu, address) : value
    
      psu := $A0 | ((psu & %111) << 1)  
    
      i2c.start
      i2c.write(psu) 
      i2c.write(address)
      i2c.start
      i2c.write(psu | 1) 
      value := i2c.read(i2c#NAK)
      i2c.stop
    
    
    pub write_byte(psu, address, value)
    
      psu := $A0 | ((psu & %111) << 1)
    
      i2c.start
      i2c.write(psu)
      i2c.write(address)
      i2c.write(value)
      i2c.stop
    
  • Thank you JonnyMac,
    I will test your mentioned changes and the tool tomorrow.

    you wrote at least 4.7kOhm, Wich impact has the value of the Resistor?
    I will give the 3.3V a try, and will order some converter.

    With the more generic code you are absolutley right.
    Normaly when Im working in a new topic i try to keep things simple as possible, to make bug huntung and understanding much easier.

    Regards
    PiJay

  • JonnyMacJonnyMac Posts: 9,144
    edited 2022-12-22 18:36

    you wrote at least 4.7kOhm, Wich impact has the value of the Resistor?

    If you use 4.7K with a 5v bus this will limit the current through the Propellers pin-protection diodes to a safe level. If you use 3.3v for your I2C bus, you can use 2.2K which will give you a "stiffer" bus, but I don't think that's necessary here.

    Normaly when Im working in a new topic i try to keep things simple as possible, to make bug huntung and understanding much easier.

    I have found in a lot of years of writing code that "simple" often obfuscates problems; one might as well write code correctly to start with. My opinion is that "quick and dirty" is never quick, but always dirty.

    I write a lot of little tools (like the one I attached above) so that I don't have to rewrite "simple" code.

  • I just saw this in your first post

    (on 28/29 i got propblems by flashing the board)

    This means the device is set to $A0, or it could mean it doesn't like the speed at which the Propeller communicates with its EEPROM, which -- if I recall -- is about 225kHz. It's definitely faster than standard I2C, but slower than high-speed I2C. I found this while doing a client design and could not share the I2C bus with an external device because that [max 100kHz] device corrupted communications between the Propeller and its EEPROM.

  • @JonnyMac said:
    This means the device is set to $A0, or it could mean it doesn't like the speed at which the Propeller communicates with its EEPROM, which -- if I recall -- is about 225kHz. It's definitely faster than standard I2C, but slower than high-speed I2C. I found this while doing a client design and could not share the I2C bus with an external device because that [max 100kHz] device corrupted communications between the Propeller and its EEPROM.

    True, the PSU was set in $A0. But also, when I am Changing the adress of the PSU, Onyl the EEprom is found.

    Your i2c Device-Finder-Programm works fine, Thanks a lot for that!
    Readout of EEProm works as schon by your screenshot. With the PSU I get on 3.3V (4.7kOhm) Every adress and, the Programm stops on 50 -> so no propper comunication. on 5V (4.7kOhm) i got problems as well Programm stoped. So I will need a logic cconverter as you mentioned.

  • First of all. Happy New Year!

    Little Update:

    I managed to get comunication to the PSU with your help. The Logic / Level Shifter are necessary on this project, then pin 28/29 also works (set the adress of the PSU to $A6). great advantage the pullup resistors are buit in with 10kOhm.

    In the beginning i got no ACK when using the I2C.present(slaveid) function. So, i built in a routine waitng the master to get a ACK from my slave.
    When plying with some timig/waiting I got the feeling that this can occur some trouble.
    So my buest guess the "strechted clock" can somtimes mess things up?

    The acces to the control register works well (1byte). At the momant I am struggling with 2 byte Setting. (acces to two register adresses an two values, followed with an update comand)

Sign In or Register to comment.