4

As already mentioned in this question Reading and writing with smbus package, there are chips that, apart for standard SDA and SCL lines, use a third communication line. This means that this "modified" I2C communication cannot be made using standard kernel and smbus library, which advantage is that communication is very orderly (perfect SCL pulses).

I already managed to bitbang communication using RPi.GPIO library. The communication works, but it is uneven and each clock pulse has different length, since RPi.GPIO library (and probably Python itself) is just too slow.

Now I want to write my own library for the communication with the chip. In order for library to work properly, I have to solve two problems:

  1. Would it be appropriate to use standard I2C Raspberry Pi pins (GPIO2, GPIO3) plus one arbitrary GPIO for that? Maybe this is not good idea because it might create a conflict with kernel and smbus library? What do you think?

  2. How should I write this communication to be as orderly as possible - should I write special C routines within my Python program and what commands should I use to access the GPIOs?

I would prefer stand-alone solutions that don't use existing communication libraries (e.g. RPi.GPIO, pigpio), since they contain a lot of capabilities completely unnecessary for the problem.

10
  • 1
    Let us first agree on Rpi4B pinout: imgur.com/gallery/2bwBacj.
    – tlfong01
    Feb 3, 2020 at 12:25
  • Let us also agree on the version of the datasheet MCP4728 Quad 12-Bit DAC EEPROM Datasheet - DS22187E 2010 Microchip ww1.microchip.com/downloads/en/devicedoc/22187e.pdf.
    – tlfong01
    Feb 3, 2020 at 12:37
  • Your proposal is a bit confusing. Let us focus on the LDAC pin how your extra line/signal can deal with it:(1) penzu.com/p/a42cfe42. I need to read the datasheet one more time and ask you some questions for clarification, perhaps tomorrow.
    – tlfong01
    Feb 3, 2020 at 13:36
  • (1) On second thought, I think I better as soon as possible give my comments on the OP's proposal of using 3 lines as a new version of I2C, because I don't wish to mislead others to think that we should discuss this proposal further. I would suggest to move this question to the EE stackExchange, and let the EE guys give their opinions. (2) I am interested in this DAC + EEPROM chip because I have been using this type of chips for my Micky Mouse projects on PID servo control and digitized volume control of audio power amplifiers. / to continue, ...
    – tlfong01
    Feb 3, 2020 at 15:01
  • MCP4728 as the datasheet says, is very useful for these applications of mine. (2) But I STRONGLY DISAGREE and think that the OP's suggestion of a 3 line I2Cis AMATEURISH. I read the LDAC signal description again and I don't think anything wrong to use Rpi GPIO to control the LDAC input. If we don't want to use one more signal line for GPIO/LDAC, an alternative is to use a I2C interfaced MCP23017 GPIO.
    – tlfong01
    Feb 3, 2020 at 15:09

2 Answers 2

2
+100

That LDAC signal is truly nasty.

I have read the datasheet and your messages a few times and I can't quite focus on a specific issue so I figure out you're just brainstorming. I will start from what I know from direct experience.

How should I write this communication to be as orderly as possible - should I write special C routines within my Python program and what commands should I use to access the GPIOs?

I can confirm an ad-hoc, C (then C++) program to drive the pins improves regularity massively. I observed this in multiple experiments over a few significantly different devices with scope. At work, I use this to switch our radio chip from 'end of transmission' to 'be back in receive mode' and it has >99% reliability vs <66% for the higher level approaches. To reach this, you need to write the program in a peculiar way:

  • no-alloc: everything must be on stack so no malloc and no new.
  • GPIO access: just memory map /dev/gpiomem. That exposes the hardware-level ARM AXI AMBA registers. You can't get any faster than that!
  • for I/O I suggest a Unix-domain socket. I encourage use of a binary protocol.

I speculate the result is the OS sees a minuscule program which it can schedule easily. Compare to higher level languages which often have threading and task facilities, an extensive io.

Nice helps. The new realtime priority system helps. Neither gave me the same result as writing this program. I doubt just binding python to a C library would do either.

I suspect the choice of pins could be subjective.

4
  • 1
    I think you gave the most extensive answer so far. However as an amateur programmer I am not as experienced in C as in Python. Is it possible to give just a very short example of writing and reading one bit from Raspberry Pi GPIO using the three conditions above? Also, since the communication is really short (consisting of reading/writing 32 bits/4 bytes), would calling C code from Python be OK? I have already figured out communication in Python, so I will manage to do that myself.
    – Pygmalion
    Feb 15, 2020 at 10:39
  • 1
    I did some searching, and I believe Tiny and Minimal GPIO Access on abyz.me.uk/rpi/pigpio/examples.html explain out your second point.
    – Pygmalion
    Feb 16, 2020 at 9:21
  • 1
    Update: I succeed to big bang the communication in C and I got fairly regular communication of about 90 kHz (ideally it would be 100 kHz). The only problem that appears is that sometimes computer decides to do something in the middle of communication, giving nasty gap. I guess this cannot be completely solved.
    – Pygmalion
    Feb 19, 2020 at 17:34
  • 1
    Something will always stay there. Thank you for the update!
    – MaxDZ8
    Feb 20, 2020 at 18:40
2

A few thoughts:

  1. Using dedicated I2C pins for your bit-banged I2C should be fine as long as you don't use smbus at the same time.

  2. Improving GPIO timing in userspace can be done by increasing process priority (see man nice). Re-writing your bit-banging routines in C will help on average, but the worst case will be just as bad as with Python. The only way to get consistent timing is to move your code to a kernel module.

I2C is designed to handle inconsistent timing (both master and slave can make a clock cycle almost arbitrarily long if they need more time), so as long as the communication works, I wouldn't worry about uneven clock pulses too much.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.