Continue to Site

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.

  • 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.

Communicating with SRF05 using PIC18f452

Status
Not open for further replies.

jagjit.sehra

New Member
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.
 
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:
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:
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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++);

}
 
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:
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.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top