1

I have a problem with my i2c library on raspberry pi zero.

I have written my code in python using many tutorials but none of them was fully sufficient. In this code time.sleep() is missing, but even when included, problem still exists. It can communicate with device but inproperly. It was tested on device BME280.

import RPi.GPIO as GPIO
import time

class SMBus(object):

    pin_SCL = 0
    pin_SDA = 0
    signal = []

    def __init__(self, bus=-1):
        GPIO.setmode(GPIO.BOARD)
        self.set_pin(13, 11)
        self.start()

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


    def start(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)

        GPIO.output(self.pin_SCL, GPIO.HIGH)
        GPIO.output(self.pin_SDA, GPIO.HIGH)

        GPIO.output(self.pin_SDA, GPIO.LOW)
        GPIO.output(self.pin_SCL, GPIO.LOW)

    def stop(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)

        GPIO.output(self.pin_SDA, GPIO.LOW)

        GPIO.output(self.pin_SDA, GPIO.HIGH)
        GPIO.output(self.pin_SCL, GPIO.HIGH)


    def send_byte(self, byte):
        GPIO.setup(self.pin_SDA, GPIO.OUT)

        for i in range(8):
            GPIO.output(self.pin_SDA, byte & 0b10000000)
            GPIO.output(self.pin_SCL, GPIO.HIGH)
            GPIO.output(self.pin_SCL, GPIO.LOW)
            byte = byte << 1


    def acknowledge_from_slave(self):
        GPIO.setup(self.pin_SDA, GPIO.IN)

        GPIO.output(self.pin_SCL, GPIO.HIGH)
        status = GPIO.input(self.pin_SDA)
        GPIO.output(self.pin_SCL, GPIO.LOW)

        if (status == GPIO.HIGH):
            print("BYTE NOT RECEIVED")


    def acknowledge_from_master(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)

        GPIO.output(self.pin_SCL, GPIO.HIGH)
        GPIO.output(self.pin_SDA, GPIO.LOW)
        GPIO.output(self.pin_SCL, GPIO.LOW)


    def receive_byte(self):
        byte = ''

        GPIO.setup(self.pin_SDA, GPIO.IN)

        for i in range(8):
            GPIO.output(self.pin_SCL, GPIO.HIGH)
            byte = byte + str(GPIO.input(self.pin_SDA))
            GPIO.output(self.pin_SCL, GPIO.LOW)

        byte = int(byte, 2)
        return byte

    def write_byte_data(self, DEVICE, address, byte):
        self.start()
        self.send_byte(DEVICE*2+0)
        self.acknowledge_from_slave()
        self.send_byte(address)
        self.acknowledge_from_slave()
        self.send_byte(byte)
        self.acknowledge_from_slave()

    def read_byte_data(self, DEVICE, address):
        self.start()
        self.send_byte(DEVICE*2+1)
        self.acknowledge_from_slave()
        self.send_byte(address)
        self.acknowledge_from_master()
        return self.receive_byte()

I expect to get proper temperature from my device (BME280).

  • Are you sure you are not violating some timing constraints in that code. And now that I read more of the code I'm not sure it is in spec for I2C at all. – r_ahlskog Jan 08 '19 at 10:55

1 Answers1

0

You were very close. Here is working solution:

import RPi.GPIO as GPIO
import time

class SMBus(object):

    pin_SCL = 0
    pin_SDA = 0
    delay = 0.001


    def __init__(self, bus=-1):
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BOARD)
        self.set_pin(11, 13)
        self.start()


    def set_pin(self, SDA, SCL):
        self.pin_SCL = SCL
        self.pin_SDA = SDA
        GPIO.setup(self.pin_SCL, GPIO.OUT)
        time.sleep(self.delay)


    def start(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)
        GPIO.output(self.pin_SDA, GPIO.HIGH)
        GPIO.output(self.pin_SCL, GPIO.HIGH)
        time.sleep(self.delay)
        GPIO.output(self.pin_SDA, GPIO.LOW)
        time.sleep(self.delay)


    def repeated_start(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)
        GPIO.output(self.pin_SCL, GPIO.LOW)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SDA, GPIO.HIGH)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SCL, GPIO.HIGH)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SDA, GPIO.LOW)
        time.sleep(self.delay)


    def stop(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)
        GPIO.output(self.pin_SCL, GPIO.LOW)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SDA, GPIO.LOW)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SCL, GPIO.HIGH)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SDA, GPIO.HIGH)
        time.sleep(self.delay)


    def send_ack(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)
        GPIO.output(self.pin_SCL, GPIO.LOW)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SDA, GPIO.LOW)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SCL, GPIO.HIGH)
        time.sleep(self.delay)


    def send_nack(self):
        GPIO.setup(self.pin_SDA, GPIO.OUT)
        GPIO.output(self.pin_SCL, GPIO.LOW)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SDA, GPIO.HIGH)
        time.sleep(self.delay/2)
        GPIO.output(self.pin_SCL, GPIO.HIGH)
        time.sleep(self.delay)


    def send_byte(self, byte):
        GPIO.setup(self.pin_SDA, GPIO.OUT)

        for i in range(8):
            GPIO.output(self.pin_SCL, GPIO.LOW)
            time.sleep(self.delay)
            GPIO.output(self.pin_SDA, byte & 0b10000000)
            time.sleep(self.delay/2)
            GPIO.output(self.pin_SCL, GPIO.HIGH)
            time.sleep(self.delay)
            byte = byte << 1

        self.send_ack()


    def receive_byte(self):
        byte = ''

        for i in range(8):
            GPIO.setup(self.pin_SDA, GPIO.OUT)
            GPIO.output(self.pin_SCL, GPIO.LOW)
            GPIO.output(self.pin_SDA, GPIO.HIGH)
            time.sleep(self.delay)
            GPIO.output(self.pin_SCL, GPIO.HIGH)
            time.sleep(self.delay/2)
            GPIO.setup(self.pin_SDA, GPIO.IN)
            byte = byte + str(GPIO.input(self.pin_SDA))
            time.sleep(self.delay)

        byte = int(byte, 2)
        return byte


    def write_byte_data(self, DEVICE, address, byte):
        self.start()
        self.send_byte(DEVICE*2+0)
        self.send_byte(address)
        self.send_byte(byte)
        self.stop()


    def read_byte_data(self, DEVICE, address):
        self.start()
        self.send_byte(DEVICE*2+0)
        self.send_byte(address)

        self.repeated_start()

        self.send_byte(DEVICE*2+1)
        byte = self.receive_byte()
        self.send_nack()
        self.stop()

        return byte
lunesco
  • 126
  • 3
  • 9