1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Communicating with SRF05 using PIC18f452

Discussion in 'Robotics & Mechatronics' started by jagjit.sehra, Feb 8, 2008.

  1. jagjit.sehra

    jagjit.sehra New Member

    Joined:
    Feb 8, 2008
    Messages:
    7
    Likes:
    0
    Hi Folks,
    I am new to this foroumn, I am intrested in interfacing the SRF05 ultra-range sensors to the PIC18F452 using MPLAB lab enviroment and the C18 complier. The complier already has commands built in to communicate on the I2C bus. The program that I have written however returns no value fromteh internal register of the sensor after ranging. The code is shown below. I am new to this therefore there may be some obvious mistakes that I cant see.
    #include <p18f452.h>
    #include <sw_i2c.h>


    void start(void);
    void read(void);
    void ack_poll(void);
    unsigned char var;
    unsigned char value;
    unsigned char i;
    unsigned char rarr[2];
    unsigned char far *rdptr = rarr;
    void main(void)
    {


    start();
    ack_poll();
    read();
    Nop();




    }

    void start(void)
    {
    SWStartI2C();
    var=SWPutcI2C(0xE0);
    SWAckI2C();
    var=SWPutcI2C(0x00);
    SWAckI2C();
    var=SWPutcI2C(0x51);
    SWAckI2C();
    SWStopI2C();
    Nop();
    }
    void read(void)
    {
    //unsigned char new;
    SWStartI2C();
    var=SWPutcI2C(0xE0);
    SWAckI2C();
    var=SWPutcI2C(0x00);
    SWAckI2C();
    SWRestartI2C();
    var=SWPutcI2C(0xE1);
    value=SWGetsI2C(rdptr,2);
    //new=SWReadI2C();
    var=SWAckI2C();
    Nop();
    SWStopI2C();
    Nop();
    }

    void ack_poll(void)
    {
    SWStartI2C();
    var=SWPutcI2C(0xE0);
    while(SWAckI2C()){
    SWRestartI2C();
    var=SWPutcI2C(0xE0);
    }
    SWStopI2C();

    }

    I have been going mad trying to get it to return some values with no success. Any help will therefore be appreciated. Thanks.

    Jag.
     
  2. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    9,886
    Likes:
    306
    Location:
    Brisbane Australia
    Here's some code I wrote to write to a serial EEPROM. It may give you some ideas.

    Mike.
    P.S. you probably want to look at the last 2 routines.
    Code (text):


    void InitI2C();
    void WaitSSP();
    void SendStart();
    void SendStop();
    void SendRestart();
    char SendByte(char);
    char ReceiveByte();
    void SendNack();
    void SendAck();
    char WriteByte(int,char);
    char ReadByte(int);

    //initialise the MSSP module
    void InitI2C(){
        TRISBbits.TRISB0=1;
        TRISBbits.TRISB1=1;
        SSPCON1=0b00101000;
        SSPCON2=0;
        SSPSTAT=0b10000000;
        SSPADD=50;  //20000/(4*100);   //Fosc/(4*baud)
        PIR1bits.SSPIF=0;
        PIR2bits.BCLIF=0;
    }

    //Wait for the module to finish it's last action.
    void WaitSSP(){
        while(PIR1bits.SSPIF==0);
        PIR1bits.SSPIF=0;
    }

    //send start bit
    void SendStart(){
        SSPCON2bits.SEN=1;
        WaitSSP();
    }

    //Send stop bit.
    void SendStop(){
        SSPCON2bits.PEN=1;
        WaitSSP();
    }

    //Send restart bit
    void SendRestart(){
        SSPCON2bits.RSEN=1;
        WaitSSP();
    }

    //Send byte and return ack bit - 1=Ack  0=NAck
    char SendByte(char Byte){
        SSPBUF=Byte;
        WaitSSP();
        return(!SSPCON2bits.ACKSTAT);
    }

    //Get a byte from the slave
    char ReceiveByte(){
        SSPCON2bits.RCEN=1;
        WaitSSP();
        return(SSPBUF);
    }

    //Send a Not Acknowledge (NAck) to the slave
    void SendNack(){
        SSPCON2bits.ACKDT=1;
        SSPCON2bits.ACKEN=1;
        WaitSSP();
    }

    //Send an Acknowledge (Ack) to the slave
    void SendAck(){
        SSPCON2bits.ACKDT=0;
        SSPCON2bits.ACKEN=1;
        WaitSSP();
    }

    //Sends the start and device address.
    //If the device is busy then it resends until accepted.
    void SendID(char DeviceID){
        SendStart();
        if(SendByte(DeviceID)==1)
            return;
        do{
            SendRestart();
        }while(SendByte(DeviceID)==0);
    }

    //Write a byte to 24LC256
    char WriteByte(int Address, char Byte){
        SendID(0b10100000);
        if(SendByte(Address>>8)==0)
            return(0);
        if(SendByte(Address&0xff)==0)
            return(0);
        if(SendByte(Byte)==0)
            return(0);
        SendStop();
        return(1);
    }

    //Read a byte from a 24LC256
    char ReadByte(int Address){
    char Byte;
        SendID(0b10100000);
        if(SendByte(Address>>8)==0)
            return(0);
        if(SendByte(Address&0xff)==0)
            return(0);
        SendRestart();
        if(SendByte(0b10100001)==0)
            return(0);
        Byte=ReceiveByte();
        SendNack();
        SendStop();
        return(Byte);
    }
     
    Last edited: Feb 8, 2008
  3. jagjit.sehra

    jagjit.sehra New Member

    Joined:
    Feb 8, 2008
    Messages:
    7
    Likes:
    0
    Hi Mike,
    Thank you very much for your reply, however I am afraid you may have to spell it out for me as I am very new to this field. I am using a 20 MHz clocck for the PIC is that what the problem as the SRF05 uses a speed of 100 khz.
    Cheers Jag.
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. jagjit.sehra

    jagjit.sehra New Member

    Joined:
    Feb 8, 2008
    Messages:
    7
    Likes:
    0

    I2C bus and SRF05 sensor module

    Hi Folks,
    I feel that I must clarify at what stage I have got to and where I am experiencing difficulties. I am trying to design and build an Autonomous Guided Vehicle. I am using the PIC18F452 micro-controller and the sensors I chose were the SRF05 ultra-range sensors. Communication is via the I2C bus protocol.
    I have researched into the protocol and had a look at various timing diagrams.
    I have connected the SRF05 to my micro-controller the SDA line of the PIC was connected to the Echo output and SCL connected to the TRIGGER line of Sensor. The code that I have was activating the sensor as LED on sensor flashes every time I execute the code, however that’s as far as I get. When I read the array there is nothing in it. I have listed all the code again with comments in this time. Can someone please please tell me where I am going wrong?

    #include <p18f452.h>// PIC header file
    #include <sw_i2c.h> // I2C header file (Functions in the Microchip C18 compiler)

    //Function prototypes

    void start(void);
    void read(void);
    void ack_poll(void);

    // Variable declarations

    unsigned char var;
    unsigned char value;
    unsigned char i;

    // Declaration of an array of 2 8-bit elements

    unsigned char rarr[2];

    // Declaration of pointer and assign address of element 0 of array
    unsigned char far *rdptr = rarr;
    // Start of main function

    void main(void)
    {
    // Function calls
    start();
    ack_poll();
    read();
    Nop();
    }



    void start(void)
    {
    SWStartI2C(); // Start bit

    //E0 includes the 7-bit slave address(default E0) and 1 read write bit (Write = 0 //and Read = 1)

    var=SWPutcI2C(0xE0);

    //Send Aknowledge to slave

    SWAckI2C();

    // Write to internal register of SRF05

    var=SWPutcI2C(0x00);

    //Send Acknowledge to slave

    SWAckI2C();

    // Write to 0x51 to the internal register of SRF05 (start Ultra-Ranging)

    var=SWPutcI2C(0x51);

    //Send Acknowledge to slave

    SWAckI2C();

    SWStopI2C(); // Stop bit to release slave from bus

    Nop();

    }


    void read(void)
    {

    SWStartI2C(); // Start bit

    //E0 includes the 7-bit slave address (default E0) and 1 read write bit (Write = 0 //and Read = 1)

    var=SWPutcI2C(0xE0);

    //Send Acknowledge to slave

    SWAckI2C();

    // Write to internal register of SRF05

    var=SWPutcI2C(0x00);

    //Send Acknowledge to slave

    SWAckI2C();

    SWRestartI2C(); // Restart bit

    //E1 includes the 7-bit slave address (default E0) and 1 read write bit (Write = 0 //and Read = 1)

    var=SWPutcI2C(0xE1);

    //Read the internal register it should contain value which is distance in // //centimeters. I guess if anywhere I am doing something wrong here!

    value=SWGetsI2C(rdptr,2);

    // Wait for Acknowledgment from slave. I know this is the same function as I have //been using for sending Acknowledgement. I think it does both or maybe it //doesn’t

    var=SWAckI2C();

    Nop(); // I have added Nop(); to create breakpoints for de-bugging

    SWStopI2C(); // Send stop bit.

    Nop();

    }

    // waiting for the return value to be zero which confirms slave has acknowledged

    void ack_poll(void)
    {
    SWStartI2C();
    var=SWPutcI2C(0xE0);
    while(SWAckI2C()){
    SWRestartI2C();
    var=SWPutcI2C(0xE0);
    }
    SWStopI2C();

    }

    I am not looking for straight answers more so a friend to point me in the right direction. Thanks in advance for your help.
     
  6. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    9,886
    Likes:
    306
    Location:
    Brisbane Australia
    You seem to be a little confused about how I²C works. You are sending address 0xa0 which is the address for a serial EEPROM. The address for the SRF is not defined as it isn't an I²C device. If you get a SRF10 then you may be more successful.

    Mike.
     
  7. jagjit.sehra

    jagjit.sehra New Member

    Joined:
    Feb 8, 2008
    Messages:
    7
    Likes:
    0
    Srf05

    Hi Mike,
    You are definatly right there, I am confused about the I2C bus, however I read that the default address for the SRF05 is 0xE0 in hex, the internal register address is 0x00 and the command to start it ranging in centimetres is 0x51 which should be written to the command register.
    i have spotted a mistake in my own work that is that at the end of read and write I should be sending a Not Ack and I have been sendingh Ack.
    Can you spot any other glaring mistakes.

    Cheers mate.
     
  8. Nigel Goodwin

    Nigel Goodwin Super Moderator Most Helpful Member

    Joined:
    Nov 17, 2003
    Messages:
    38,985
    Likes:
    616
    Location:
    Derbyshire, UK
    ONLINE
    You seem to far more confused than that?, the SRF05 isn't an I2C device, you simply pulse it's trigger pin high and measure the width of the return pulse on the echo pin (in mode 2, you can use a single pin for both trigger and echo). Mode 1 uses separate pins for trigger and echo.

    So you're trying completely the wrong approach, and it can never work.

    There are various others in the series that are I2C, but the SRF05 isn't one of them.
     
  9. jagjit.sehra

    jagjit.sehra New Member

    Joined:
    Feb 8, 2008
    Messages:
    7
    Likes:
    0
    Srf05

    Hi Folks,
    Thanks for the advice, I can see now that its the SRF08 I need to use as that is compatible with the I2C bus. I got some bad advice of a coleague.
    However thanks for showing this enormous floor in my work. Will use the SRF08 and hopefully that will work.

    Cheers Jag.
     
  10. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    9,886
    Likes:
    306
    Location:
    Brisbane Australia
    Good luck, I hope it all works out well.

    Mike.
     
  11. jagjit.sehra

    jagjit.sehra New Member

    Joined:
    Feb 8, 2008
    Messages:
    7
    Likes:
    0
    SRF08 and PIC18F452

    After the enormous mistake of trying to communicate with the SRF05 using the I2C bus protocol even though that particular sensor doesnt support it.
    I am still having difficulties in reading a value back. I am now using the SRF08 which does support the I2C protocol and the PIC18F452 as the master. I am using the microchip C18 compilier which has macros for the communication. However I am alaways reading the same value for my low byte. Can anyone show me the light an dtell me what I am doing wrong. I read somewhere that the C18 macros do not reduce the speed to 100 kHz and I would have to do that myself by assigning the register in my code
    (SSPADD=99). My code is shown below.


    #include <p18f452.h>
    #include <sw_i2c.h>

    void start(void);
    void read(void);
    void ack_poll(void);
    void delay(void);
    unsigned char var;
    unsigned char value;
    unsigned char i;
    unsigned char hibyte, lobyte;
    unsigned char i;


    void main(void)
    {


    start();
    delay();//delay will last 70 ms. Enough time for ranging to complete!
    read();
    Nop();




    }

    void start(void)
    {
    SWStartI2C(); // Alert all slaves to listen
    var=SWPutcI2C(0xE0); // default address
    SWAckI2C();
    var=SWPutcI2C(0x00); //Internal register
    SWAckI2C();
    var=SWPutcI2C(0x51); // Start ranging in centi-metres
    SWAckI2C();
    SWStopI2C(); // Free bus
    }



    void read(void)
    {

    SWStartI2C();
    var=SWPutcI2C(0xE0); // Address slave
    SWAckI2C();
    var=SWPutcI2C(0x02); // write to the register which contains high byte
    SWAckI2C();
    SWRestartI2C(); // restart
    var=SWPutcI2C(0xE1); // Address slave but this time send a read bit
    SWAckI2C();
    hibyte=SWReadI2C(); // Read high byte
    SWAckI2C();
    lobyte=SWReadI2C(); //Read low byte. There is no need to send acknowledgement on the last byte read
    SWStopI2C();
    Nop();
    }


    void delay(void)
    {
    unsigned double j;

    for(j=0;j<=1000;j++);

    }
     
  12. Pommie

    Pommie Well-Known Member Most Helpful Member

    Joined:
    Mar 18, 2005
    Messages:
    9,886
    Likes:
    306
    Location:
    Brisbane Australia
    You should only send an Ack after you receive a byte. When sending you should receive an Ack. You should also send a NAck to receive the last byte prior to sending a stop. I assume the SWPutcI2C returns Ack/Nack.

    Edit, just looked and the software I2C routines are not as simple to use as the hardware. You have to setup the data and clock pins by recompiling the library. Assuming your using RC4 and RC3 as your data and clock pins it would be easier to use the hardware routines in i2c.h

    Mike.
     
    Last edited: Feb 12, 2008
  13. jagjit.sehra

    jagjit.sehra New Member

    Joined:
    Feb 8, 2008
    Messages:
    7
    Likes:
    0
    Abort Software macros

    Hi Mike,
    I wa sdefinatley barking up the wrong tree trying to use the software macros included with the Microchip compilier. I had a look at the source code for the functions which includes another header file which contains the source code for that. I have opted to go for the hrdware functions which access the registers directly much more simpler. Thanks for all you advice mate! If anyone is intrested in using the I2C I would advice not to use the software function route

    Cheers Jag.
     

Share This Page