Bit Banging I2C for communication between Raspberry Pi and PCF8591

Status
Not open for further replies.

John Manuel

New Member
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:
import RPi.GPIO as GPIO
import time
import matplotlib.pyplot as plt

pin_SCL = 0
pin_SDA = 0
signal = []

def plot_graph(time, data, graph_no, label_):
    fig = plt.figure(graph_no)
    axes = fig.add_subplot(111)
    axes.patch.set_facecolor('black')
    plt.plot(time, data, label = label_)
    plt.ylabel('Voltage')
    plt.xlabel('Time')
    plt.legend(loc='upper right')

def set_pin(SCL, SDA):
    global pin_SCL
    global pin_SDA
    pin_SCL = SCL
    pin_SDA = SDA
    GPIO.setup(pin_SCL, GPIO.OUT)

def start():
    GPIO.setup(pin_SDA, GPIO.OUT)
   
    GPIO.output(pin_SCL, GPIO.HIGH)
    GPIO.output(pin_SDA, GPIO.HIGH)
   
    time.sleep(10)
   
    GPIO.output(pin_SDA, GPIO.LOW)
    GPIO.output(pin_SCL, GPIO.LOW)
   
def send_byte(byte):
    GPIO.setup(pin_SDA,GPIO.OUT)
   
    for i in range(8):
        GPIO.output(pin_SDA,byte & 0b10000000)
        GPIO.output(pin_SCL,GPIO.HIGH)
        GPIO.output(pin_SCL,GPIO.LOW)
        byte = byte << 1

def acknowledge_from_slave():
    GPIO.setup(pin_SDA,GPIO.IN)
   
    GPIO.output(pin_SCL,GPIO.HIGH)
    status = GPIO.input(pin_SDA)
    GPIO.output(pin_SCL,GPIO.LOW)
   
    if(status == GPIO.HIGH):
        print("BYTE NOT RECEIVED")
           
def acknowledge_from_master():
    GPIO.setup(pin_SDA,GPIO.OUT)
   
    GPIO.output(pin_SCL,GPIO.HIGH)
    GPIO.output(pin_SDA,GPIO.LOW)
    GPIO.output(pin_SCL,GPIO.LOW)

def receive_byte():
    global signal
    byte = ''
   
    GPIO.setup(pin_SDA,GPIO.IN)
   
    for i in range(8):
            GPIO.output(pin_SCL,GPIO.HIGH)
            byte = byte + str(GPIO.input(pin_SDA))
            GPIO.output(pin_SCL,GPIO.LOW)
   
    byte = int(byte,2)
    signal.append(byte)
           
if __name__ == "__main__":
    global signal
   
    GPIO.setmode(GPIO.BOARD)
    set_pin(38,40)
    start()
    send_byte(0b10010001)
    acknowledge_from_slave()
   
    send_byte(0b00110000)#control byte to tell pcf8591 work as differential input
   
    acknowledge_from_master()

    try:
        while True:
            receive_byte()
            acknowledge_from_master()
           
    except KeyboardInterrupt:
        plot_graph(range(len(signal)),signal,1,'Detected Signal')

    plt.show()
    GPIO.cleanup()
 
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.

Sorry, but you appear to be trying to use devices without the slightest idea of how to do so - the whole point of I2C (and it's huge advantage over SPI) is that chips are individually addressable, and the PCF8591 has three address pins, so you can select any one of 8 addresses, thus you can connect eight different PCF8591's to the same I2C bus, with each having it's own address. You really need to study the datasheet for the device, and I2C in general.

I don't think it will be much help?, but here's a link to my PIC I2C tutorial, one of which uses that exact chip - but it's in PIC assembler.
 
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.

Actually, I am confused how to access different pins in a single PCF8591.
 
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.

Why would you imagine you need to do anything at the 'same instant'?, which is impossible anyway, and particularly so on a Raspberry Pi that runs a huge operating system - and operates no where near 'real time'.

Reading each device in turn on the same bus is no different to reading them in turn on separate buses, and will probably be slightly faster - particularly if you're bit-banging the other buses.

Actually, I am confused how to access different pins in a single PCF8591.

Try reading the datasheet - it explains everything - including that even on one IC you can't read all analogue inputs at the same time, you have to read them sequentially.

What exactly are you trying to do?, and why do you imagine that you need to read all inputs at the same time (which isn't going to happen).

As for multiple analogue inputs, it would probably be faster to do it with a PIC, many of which have plenty of analogue input pins - but in common with the PCF8591 (and pretty well everything else) only have one A2D, and switch it between the different inputs. So the PIC could do all the conversion, and transfer the data to the Pi - but it really depends what you're trying to do?.
 
For info, some higher PICs [ie. some DSPIC33 series we use] have multiple ADCs and can sample & convert eg. four inputs at a time.

You still have to get that info to whatever external device you are using, unless you build the whole gadget in the dspic.

Some of the latest ones, dsPIC33CH series, have two separate CPU cores so you can have one doing the time critical tasks continuously and the other handling comms or interface tasks that have delays or cause blocking at times.

(I've just got my first samples of those but not had chance to do anything with them yet).
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…