• AVR Freaks

PIC24F I2C to Raspberry Pi

Author
Olafa Pa
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2013/07/24 02:52:09
  • Location: 0
  • Status: offline
2013/07/24 03:45:46 (permalink)
0

PIC24F I2C to Raspberry Pi

Hi All,
I'm new to PIC's and PIC programming but I'm working on a little project to try get a PIC24F32KA301 to communicate with a Raspberry Pi using I2C. In this setup the Raspberry Pi is the master and the PIC is the slave. I have created a little python program on the Raspberry Pi and tested that it works by successfully communicating with an Arduino, what I want to do now is replace the Arduino with a PIC.
 
Just for completeness I've included the python program below:
 

import smbus
import time
 
bus = smbus.SMBus(1)
address = 0x22
 
def writeNumber(value):
    bus.write_byte(address, value)
    return -1
 
def readNumber():
    number = bus.read_byte(address)
    return number
 
while True:
    var = input("Enter 1 - 9: ")
    if not var:
        continue
    writeNumber(var)
    print "RPI: Hi Arduino, I sent you ", var
 
    time.sleep(1)
    number = readNumber()
    print "Arduino: Hey RPI, I received a digit ", number
    print


I'm pretty sure I've connected the PIC and Raspberry Pi correctly, e.g.  GND <---> Vss (pin 19), SCL <---> SCL1 (pin 12), SDA <---> SDA1 (pin 13). The Raspberry Pi is powered over USB (so I think that's 5V, but it might be 3V) and the PIC is powered separately using a 3V battery. The Arduino didn't have any pull up resistors so I assumed it would be ok to not have any on the PIC (maybe this is wrong?). I'm using C with the XC16 compiler and the i2c.h library to program the PIC but I'm not really sure what I'm doing, I've tried my best to piece things together from I2C examples and little bits I've read on various forums etc. My code is below:
 

#define USE_AND_OR    // not sure what this is!
#include <p24Fxxxx.h>
#include <i2c.h>

unsigned char I2C_RECV[1]

void main(void) {
    unsigned int temp, i;
    for(i=0; i<1; i++)
        I2C_RECV[i]=0;

    TRISA = 0b0000000000000000;
    PORTA = 0b0000000000000001;

    /* INITIALISE I2C MODULE  */
    CloseI2C1();                            // close i2c if it was operating earlier

    while(1) {
        OpenI2C1((I2C_ON | I2C_7BIT_ADD | I2C_CLK_REL | I2C_STR_EN), 0);
        I2C1ADD = 0x22;                     // initialze slave address to 1E

        // receive data from master
        while(DataRdyI2C1() == 0);          // wait until data is transmitted from master
        temp = SlaveReadI2C1();             // read address to empty buffer

        SlavegetsI2C1(I2C_RECV, 1);         // receive data

        if(I2C_RECV[0] == 9) {
            PORTA = 0b0000000000000011;
        }

        CloseI2C1();
    }
}

 
The code is quite simple (but probably very wrong!). Basically I initialise the I2C module and turn on an LED, then I enter a loop, open the I2C connection using address 0x22 and wait for the master to send some data. When data is received I check it's value, if it's 9 I turn on another LED.
 
On the Raspberry Pi I can confirm that the PIC is accessible by running i2cdetect -y 1. I can see the PIC at address 0x22, which gives me some confidence that I'm at least heading in the right direction! However, when I run the python program I receive an IO error, the error number is 5. I've looked around to find out what that means, but it's a very vague error, basically anything could have gone wrong!
 
I'm not sure if it's my circuit that's incorrect (i.e. do I need pull up resistors, if so how do I calculate what resistance they need to be?) or my PIC program. If anyone has any advice I'd be very very grateful.
 
Thanks.
#1

4 Replies Related Threads

    Jerry_James
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2011/03/24 10:49:58
    • Location: Microchip Technology, Inc. Chandler, AZ.
    • Status: offline
    Re:PIC24F I2C to Raspberry Pi 2013/07/24 16:58:49 (permalink)
    5 (1)
    Add 4.7K pull-ups to SDA and SCL.  The I2C data and clock pins (SDA, SCL) are open collector outputs, the resistors limit the current sunk by those pins.  So, the choice of resistor value will balance power wasted through heat dissipation versus the strength at which the I2C module can "pull-down" the line voltage.  If you choose a value too small, you'll waste power.  If you choose a value too big, you won't be able to manipulate the I2C bus lines. 
     
     As far as I know, There isn't anything special about the value 4.7K. Its a common rule-of-thumb starting choice.
    post edited by Jerry_James - 2013/07/24 17:07:07
    #2
    Olafa Pa
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2013/07/24 02:52:09
    • Location: 0
    • Status: offline
    Re:PIC24F I2C to Raspberry Pi 2013/07/25 06:28:28 (permalink)
    0
    I've placed 4.7K resistors between SDA <---> Vpp (3.3v) and SCL <---> Vpp (3.3v) but it hasn't helped. I still get IOError (ErrNo 5) from the Python script when trying to communicate with the PIC. Does the PIC program look wrong?
     
    Thanks.
    #3
    Jerry_James
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2011/03/24 10:49:58
    • Location: Microchip Technology, Inc. Chandler, AZ.
    • Status: offline
    Re:PIC24F I2C to Raspberry Pi 2013/07/25 08:46:24 (permalink)
    5 (1)
    Move the "OpenI2C1(...)" call and "I2C1ADD = 0x22" outside of (above) the while(1){...} loop, and move CloseI2C1() outside (below the while loop).
     
    It sounds like the rest of your code is correct.  The first word sent to the PIC from the I2C master is the PIC address, which you can see that you receive. Closing and re-opening the I2C peripheral will re-initialize its internal state, and it won't know that the next byte you send is intended for it. 
    #4
    Olafa Pa
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2013/07/24 02:52:09
    • Location: 0
    • Status: offline
    Re:PIC24F I2C to Raspberry Pi 2013/07/25 13:12:54 (permalink)
    0
    Strangely enough, if I move the OpenI2C1(...) and CloseI2C1() outside the while(1) { ... }, i2cdetect can no longer find the PIC! Here is the code I have now:
    #define USE_AND_OR 
    #include <p24Fxxxx.h>
    #include <i2c.h>

    unsigned char I2C_RECV[1];

    void main(void) {
        unsigned int temp, i;
        for(i=0; i<1; i++)
            I2C_RECV[i]=0;

        TRISA = 0b0000000000000000;
        PORTA = 0b0000000000000001;

        CloseI2C1();                            // close i2c if was operating earlier
        OpenI2C1((I2C_ON | I2C_7BIT_ADD | I2C_CLK_REL | I2C_STR_EN), 0);
        I2C1ADD = 0x22;                     // initialze slave address to 1E

        while(1) {
            while(DataRdyI2C1() == 0);          // wait until data is transmitted from master
            temp = SlaveReadI2C1();             // read address to empty buffer

            SlavegetsI2C1(I2C_RECV, 1);         // receive data

            if(I2C_RECV[0] == 9)
                PORTA = 0b0000000000000011;
        }

        CloseI2C1();
    }

     
    After messing around with the code for a while I found that I need to call CloseI2C1() after the call to OpenI2C1(...) in order for i2cdetect to find the PIC! For example, if I run only this code outside of any while loop i2cdetect won't find anything
    CloseI2C1(); 
    OpenI2C1((I2C_ON | I2C_7BIT_ADD | I2C_CLK_REL | I2C_STR_EN), 0);
    I2C1ADD = 0x22;

     
    However, if I add CloseI2C1() to the end then i2cdetect will find the PIC, but because it's not in a while loop the next time I run i2cdetect it can't find anything! Have I got a damaged chip or something? nothing seems to make sense!!
     
    Cheers
    post edited by Olafa Pa - 2013/07/25 13:15:13
    #5
    Jump to:
    © 2020 APG vNext Commercial Version 4.5