Bit Banging I2C for communication between Raspberry Pi and PCF8591

Discussion in 'Embedded Systems and Microcontrollers' started by John Manuel, Jul 19, 2018.

  1. John Manuel

    Thread Starter New Member

    Jun 6, 2018
    16
    0
    I am trying to interface multiple PCF8591 (around 5) to a single Raspberry Pi using I2C protocol. Since a Rpi has only one set of SDA and SCL pins, I am trying to bit-bang to make the other GPIO pins work as SDA and SCL. I am trying to use RPi.GPIO library for making the bit banging code in python.

    I don't understand how to communicate with PCF8591 even after referring to the manual plenty of times. I could not figure out how to receive data from a specific pin from PCF8591 since there are 4 pins available (AIN0, AIN1, AIN2, AIN3). I also want the input voltage as the differential voltage between two pins. It would be very helpful if anyone could tell me the steps to change and access different pins of PCF8591.

    I am attaching the code I am using. I get a reading of '255' throughout whenever I run it. It is working more or less as I could see the SCA and SDA waveforms in an oscilloscope.


    Code (Text):
    1. import RPi.GPIO as GPIO
    2. import time
    3. import matplotlib.pyplot as plt
    4.  
    5. pin_SCL = 0
    6. pin_SDA = 0
    7. signal = []
    8.  
    9. def plot_graph(time, data, graph_no, label_):
    10.     fig = plt.figure(graph_no)
    11.     axes = fig.add_subplot(111)
    12.     axes.patch.set_facecolor('black')
    13.     plt.plot(time, data, label = label_)
    14.     plt.ylabel('Voltage')
    15.     plt.xlabel('Time')
    16.     plt.legend(loc='upper right')
    17.  
    18. def set_pin(SCL, SDA):
    19.     global pin_SCL
    20.     global pin_SDA
    21.     pin_SCL = SCL
    22.     pin_SDA = SDA
    23.     GPIO.setup(pin_SCL, GPIO.OUT)
    24.  
    25. def start():
    26.     GPIO.setup(pin_SDA, GPIO.OUT)
    27.    
    28.     GPIO.output(pin_SCL, GPIO.HIGH)
    29.     GPIO.output(pin_SDA, GPIO.HIGH)
    30.    
    31.     time.sleep(10)
    32.    
    33.     GPIO.output(pin_SDA, GPIO.LOW)
    34.     GPIO.output(pin_SCL, GPIO.LOW)
    35.    
    36. def send_byte(byte):
    37.     GPIO.setup(pin_SDA,GPIO.OUT)
    38.    
    39.     for i in range(8):
    40.         GPIO.output(pin_SDA,byte & 0b10000000)
    41.         GPIO.output(pin_SCL,GPIO.HIGH)
    42.         GPIO.output(pin_SCL,GPIO.LOW)
    43.         byte = byte << 1
    44.  
    45. def acknowledge_from_slave():
    46.     GPIO.setup(pin_SDA,GPIO.IN)
    47.    
    48.     GPIO.output(pin_SCL,GPIO.HIGH)
    49.     status = GPIO.input(pin_SDA)
    50.     GPIO.output(pin_SCL,GPIO.LOW)
    51.    
    52.     if(status == GPIO.HIGH):
    53.         print("BYTE NOT RECEIVED")
    54.            
    55. def acknowledge_from_master():
    56.     GPIO.setup(pin_SDA,GPIO.OUT)
    57.    
    58.     GPIO.output(pin_SCL,GPIO.HIGH)
    59.     GPIO.output(pin_SDA,GPIO.LOW)
    60.     GPIO.output(pin_SCL,GPIO.LOW)
    61.  
    62. def receive_byte():
    63.     global signal
    64.     byte = ''
    65.    
    66.     GPIO.setup(pin_SDA,GPIO.IN)
    67.    
    68.     for i in range(8):
    69.             GPIO.output(pin_SCL,GPIO.HIGH)
    70.             byte = byte + str(GPIO.input(pin_SDA))
    71.             GPIO.output(pin_SCL,GPIO.LOW)
    72.    
    73.     byte = int(byte,2)
    74.     signal.append(byte)
    75.            
    76. if __name__ == "__main__":
    77.     global signal
    78.    
    79.     GPIO.setmode(GPIO.BOARD)
    80.     set_pin(38,40)
    81.     start()
    82.     send_byte(0b10010001)
    83.     acknowledge_from_slave()
    84.    
    85.     send_byte(0b00110000)#control byte to tell pcf8591 work as differential input
    86.    
    87.     acknowledge_from_master()
    88.  
    89.     try:
    90.         while True:
    91.             receive_byte()
    92.             acknowledge_from_master()
    93.            
    94.     except KeyboardInterrupt:
    95.         plot_graph(range(len(signal)),signal,1,'Detected Signal')
    96.  
    97.     plt.show()
    98.     GPIO.cleanup()
    99.  
     
  2. casteels

    New Member

    Mar 22, 2012
    4
    2
    PCF8591 has 3 address pins so you can address 8 of them. Why don't you connect them all to the same I2C bus?
     
    John Manuel likes this.
  3. shteii01

    AAC Fanatic!

    Feb 19, 2010
    4,418
    696
    SCL is pin 10.
    SDA is pin 9.

    Why you are wasting time with AIN0-3 is beyond me.
     
    John Manuel likes this.
  4. John Manuel

    Thread Starter New Member

    Jun 6, 2018
    16
    0
    I need data from all the ADC at the same time instant for my project. I came to know that the master can communicate with only one slave at any time instant and the other slaves have to sit idle at that time instant.
     
  5. Papabravo

    Expert

    Feb 24, 2006
    11,682
    2,455
    And the differential timing between you bit banging and the hardware I2C will destroy any concept of simultaneity you might imagine to exist. What you want is a sample and hold system for which I2C is not well suited. You need to get your head out of the dark place it seemingly inhabits.
     
    John Manuel likes this.
  6. shteii01

    AAC Fanatic!

    Feb 19, 2010
    4,418
    696
    We are talking milliseconds here. It is fast enough that it will look simultaneous.
     
    John Manuel likes this.
  7. John P

    AAC Fanatic!

    Oct 14, 2008
    1,719
    254
    I'd have thought that if you could control a port's pins all at once--a pretty simple concept--you actually could bit-bang multiple I2C channels with identical timing, both for output and input. Whether this is really worth doing is another question, though.

    Call it port-banging instead of bit-banging, maybe.
     
Loading...