Can't get data from ADS1115 I2C and PIC 18f2550.

Author
MarcoRM
New Member
  • Total Posts : 5
  • Reward points : 0
  • Joined: 2018/11/05 12:10:58
  • Location: 0
  • Status: offline
2018/11/08 16:19:05 (permalink)
0

Can't get data from ADS1115 I2C and PIC 18f2550.

Hello Everyone.
 
I'm on a project using pic 18f2550 and ads1115. I want to get analog data from ads1115 and send it to pc via usart. I haven't had any success yet because I must be forgotten something. As you will see, I tried to write some code, but I think I've made several mistakes I can't find. I've marked with asterisks blocks I can't improve.
 
Main function:
 
void I2C_init();
void I2C_wait();
void I2C_start_com();
void I2C_restart_com();
void I2C_stop();
unsigned char I2C_write(unsigned char);
unsigned char I2C_read();

//********************************************************
void ADS1115_config();
unsigned int ADS1115_read();
//********************************************************

void Eusart_init();
void putcUSART(char c);
void putsUSART(char *data);
void putrsUSART(const char *data);

//********************************************************
unsigned int conversion;
unsigned char buffer_conversion[8];
//********************************************************

int main(int argc, char** argv)
{
    OSCCONbits.IRCF=0b110;
    ADCON0bits.ADON=0;
    ADCON1bits.PCFG=0x0F;
    I2C_init();
    ADS1115_config();
    Eusart_init();
    while(1)
    {
        //********************************************************
        conversion=ADS1115_read();
        sprintf(buffer_conversion,"%u",conversion);
        putsUSART(buffer_conversion);
        putrsUSART("\n");
        __delay_ms(25);
        //********************************************************
    }
    return (EXIT_SUCCESS);
}

 
I2C Block:
 
void I2C_init()
{
    TRISBbits.TRISB0 = 1; //Setting as input as given in datasheet
    TRISBbits.TRISB1 = 1; //Setting as input as given in datasheet
    SSPSTAT = 0b10000000;
    SSPCON1 = 0b00101000; //SSP module como master
    SSPCON2 = 0b00000000;
    SSPADD = 9; //Setting Clock Speed 100kbps
}

void I2C_wait()
{
    while ((SSPCON2 & 0b00011111) || (SSPSTAT & 0b00000100)); //Transmit is in progress
}

void I2C_start_com()
{
    I2C_wait();
    SSPCON2bits.SEN = 1; //Initiate start condition
}

void I2C_stop()
{
    I2C_wait();
    SSPCON2bits.PEN = 1;
}

void I2C_restart_com()
{
    I2C_wait();
    SSPCON2bits.RSEN=1;
}

unsigned char I2C_write(unsigned char wdata)
{
    I2C_wait();
    SSPBUF = wdata; //Write data to SSPBUF
    return ACKSTAT;
}

unsigned char I2C_read()
{
    unsigned char rdata;
    I2C_wait();
    SSPCON2bits.RCEN = 1; //Receive mode enabled
    I2C_wait();
    rdata = SSPBUF; //Read data from SSPBUF.
    I2C_wait();
    SSPCON2bits.ACKDT = 1; //Acknowledge bit
    SSPCON2bits.ACKEN = 1; //Acknowledge sequence
    return rdata;
}

 
ADS1115 Block:
 
void ADS1115_config()
{
    I2C_write(0b10010000);//Communicate to slave address
    I2C_wait();
    I2C_write(0b00000001);//Command to config registers
    I2C_wait();
    I2C_write(0b10000000);//PGA: +-6.144V, Inputs: default (A0), continuous conv. mode
    I2C_wait();
    I2C_write(0b10000011);//128 SPS, Traditional comparator, active low, nonlatching, dis. ALERT/RDY
}

//********************************************************
unsigned int ADS1115_read()
{
    I2C_start_com();
    I2C_write(0b10010000);
    I2C_wait();
    I2C_write(0b00000000);
    I2C_wait();
    I2C_restart_com();
    I2C_wait();
    I2C_write(0b10010001);
    I2C_wait();
    unsigned int adc;
    adc = I2C_read(1);
    adc = adc<<8;
    adc = adc|I2C_read(0);
    I2C_stop();
    I2C_wait();
    return adc;
}

 
USART Block:
 
void Eusart_init()
{
    TRISCbits.TRISC7 = 1; // RX
    TRISCbits.TRISC6 = 0; // TX
    TXSTA = 0b00100100;
    RCSTA = 0b10010000;
    SPBRG=103;
    SPBRGH=0;
    BAUDCON = 0b00001000;
}

void putcUSART(char c)
{
    while(!PIR1bits.TXIF);
    TXREG = c;
}

void putrsUSART(const char *data)
{
    do {
        while(TXSTA1bits.TRMT == 0);
        putcUSART(*data);
    } while( *data++ );
}

void putsUSART( char *data)
{
    do {
        while(TXSTA1bits.TRMT == 0);
        putcUSART(*data);
    } while( *data++ );
}

 
I will appreciate any help to make progress while trying to answer this.
 
Thanks for all your contributions.
#1

6 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 7892
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: Can't get data from ADS1115 I2C and PIC 18f2550. 2018/11/08 16:43:37 (permalink)
    +1 (1)
    RB0 and RB1 are also analog pins.
    I cannot see any code switching them to digital mode.
     
     
    #2
    MarcoRM
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2018/11/05 12:10:58
    • Location: 0
    • Status: offline
    Re: Can't get data from ADS1115 I2C and PIC 18f2550. 2018/11/08 18:50:13 (permalink)
    0
    Hi sir:
     
    In this part of the code it is switched to digital:
     
     ADCON0bits.ADON=0;
     ADCON1bits.PCFG=0x0F;
    #3
    qhb
    Superb Member
    • Total Posts : 7892
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: Can't get data from ADS1115 I2C and PIC 18f2550. 2018/11/08 18:59:40 (permalink)
    +1 (1)
    Sorry, you're right.
    It's harder to spot on these older parts that don't have ANSEL registers, especially when there's no comment on the line. :)
     
    I see one problem in your "write" routine
    unsigned char I2C_write(unsigned char wdata)
    {
        I2C_wait();
        SSPBUF = wdata; //Write data to SSPBUF
        return ACKSTAT;
    }

    There should be a wait before you tried to read the ACKSTAT bit. You are reading it before the transfer has happened.
    Try:
    unsigned char I2C_write(unsigned char wdata)
    {
        I2C_wait();
        SSPBUF = wdata; //Write data to SSPBUF
        I2C_wait();    // wait until transfer completes
        return ACKSTAT;
    }

    Also, you are never checking the value returned by this function. Especially when you send the first byte (the slave address), you should make sure you get an ACK back. If you don't, the slave is not hearing you, and everything else is pointless.
     
    #4
    MarcoRM
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2018/11/05 12:10:58
    • Location: 0
    • Status: offline
    Re: Can't get data from ADS1115 I2C and PIC 18f2550. 2018/11/09 12:34:58 (permalink)
    0
    Thanks for your response,qhb. I will apply your advices.
     
    Do you refer to these codes for ACK and NAK?:
     
    void I2C_Master_ACK() {
        ACKDT = 0; // Acknowledge data bit, 0 = ACK
        ACKEN = 1; // ACk data enabled
        I2C_Master_Wait();
    }

    void I2C_Master_NAK() {
        ACKDT = 1; // Acknowledge data bit, 1 = NAK
        ACKEN = 1; // ACK data enabled
        I2C_Master_Wait();
    }

     
    How should I introduce into my code? I think you said they must go between reading from ads.
     
    Thanks again for another response. 
    #5
    qhb
    Superb Member
    • Total Posts : 7892
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: online
    Re: Can't get data from ADS1115 I2C and PIC 18f2550. 2018/11/09 14:12:01 (permalink)
    0
    MarcoRM
    ...
    Do you refer to these codes for ACK and NAK?:
     

    No. That is the code to send an ACK or NAK.
    I already showed you exactly what to do to actually read the ACK/NAK correctly inside I2C_Write().
    You now need to look at the value returned by your calls to I2C_Write().
    Also, I noticed you never send START or STOP when you configure the ADC
    e.g. here:
    void ADS1115_config()
    {
        I2C_start_com();
        if (I2C_write(0b10010000))    //Send slave address
        {    //here if slave address did not get ACK response
            I2C_stop();    //slave is not responding, release bud
            return;    //abort
        }
        I2C_wait();
        I2C_write(0b00000001);//Command to config registers
        I2C_wait();
        I2C_write(0b10000000);//PGA: +-6.144V, Inputs: default (A0), continuous conv. mode
        I2C_wait();
        I2C_write(0b10000011);//128 SPS, Traditional comparator, active low, nonlatching, dis. ALERT/RDY
        I2C_stop();
    }

    All your questions sound like someone who is trying to muddle through with no understanding of the I2C protocol.
    You really do need to understand how each transaction starts with a START condition, ends with a STOP condition, and every byte transfer is ACKed or NAKed.
    You should have a read of:
    https://en.wikipedia.org/wiki/I%C2%B2C
    and
    https://www.nxp.com/docs/en/user-guide/UM10204.pdf (Official I2C specification)
     
    post edited by qhb - 2018/11/09 14:13:24
    #6
    MarcoRM
    New Member
    • Total Posts : 5
    • Reward points : 0
    • Joined: 2018/11/05 12:10:58
    • Location: 0
    • Status: offline
    Re: Can't get data from ADS1115 I2C and PIC 18f2550. 2018/11/09 14:48:16 (permalink)
    0
    Hi,qhb
     
    I'm sorry if my questions sound so inquisitive, it seems I need to review the protocol. When I finish this, I'll post the improved code.
     
    Thanks for your attention and time. 
    #7
    Jump to:
    © 2018 APG vNext Commercial Version 4.5