This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1115 - Wrong signal processing? - "steps"

Other Parts Discussed in Thread: ADS1115

Hello,

I have a problem with wrong representation of voltage processed by ADC. I tried every mode (differential and sigle-ended inputs), tried to find error in my code on microcontroller side and PC's side, but cannot find the reason.

The problem is that processed voltage's bit representation seems to be wrong at 9th bit. I get something like this for voltages  that was smoothly changed on the precise voltage divider from value higher to lower. I tried also photodetector as signal source. The height between those two levels is about 256 so i thought that the problem can be related with data casting from one variable type to another but cannot find it.

  

It is visualized data taken from ADC. It looks like 9th bit is inversed.

 Here is source code of my application on microcontroller:

Code to read data from ADC  (I use C language HiTech PICC on PIC16F877A):

 unsigned int dataOut = 0;

// Transmission start
// Set Pointer Register on Conversion register
SSPIF = 0;
ACKSTAT = 1;
SEN = 1;
while(SEN);
SSPIF = 0;

// Address
SSPBUF = 0b10010000;
while(!SSPIF);
while(ACKSTAT);
SSPIF = 0;
ACKSTAT = 1;

// Pointer Register
SSPBUF = 0b00000000;
while(!SSPIF);
while(ACKSTAT);
SSPIF = 0;
ACKSTAT = 1;
PEN = 1;
while(PEN);

// Read Data from ADC
ACKSTAT = 1;
SEN = 1;
while(SEN);
SSPIF = 0;

// Address
SSPBUF = 0b10010001;
while(!SSPIF);
SSPIF = 0;

// Read MSB
RCEN = 1;
while(!BF);
while(!SSPIF);
SSPIF = 0;
ACKEN = 1;
while(!SSPIF);
SSPIF = 0;
dataOut |= (SSPBUF << 8);

// Read LSB
RCEN = 1;
while(!BF);
while(!SSPIF);
SSPIF = 0;
ACKEN = 1;
while(!SSPIF);
SSPIF = 0;
dataOut |= SSPBUF;

// Transmission End PEN = 1;
while(PEN);
return dataOut;

then i send this data through RS-232 to PC

// Divide 2 byte variable on two bytes
unsigned char byte0 = dataOut;
unsigned char byte1 = (dataOut >> 8);

// Send byte throught RS-232
putch(byte0);
putch(byte1);

then on PC side i join two bytes into one 16bits variable

unsigned short detector1 = (unsigned short)byte0 + ((unsigned short)byte1 << 8);

And then send it into chart.

Please help me, I can add more informations if you need them.

ADC is set on continuous conversation, i can change sampling rate from 8 to 860 sps in program, can freely change adc's inner voltage reference gain, it doesn't affect on that problem behavior.
Before reading data I always wait period of time equal to two cycles of sampling rate but even in one shot mode behavior is the same.

Data shown on chart was obtain when ADC was in differential mode with +-2.048V voltage reference, 128 sps, second differential channel was short to ground.

 Here is picture of basic, testing circuit:

  

  • Lukasz,

    Welcome to the forum! Have you looked at your data on the I2C bus with a scope?  Is it possible for you to send oscilloscope pictures of the data transaction when reading?  How fast is your I2C communication? Depending on communication speed, you might be seeing an issue with response time of the bus due to capacitance on the lines.  Have you tried using smaller resistor values on the I2C pull-ups?

    Best regards,

    Bob B

  • Thank you for response. 

    "Have you looked at your data on the I2C bus with a scope?"

    No, i thought that if behavior of my device is consequently the same (error - offset occurs always in the same place) I2C communication should be correct. But i will try to check it.

    " Is it possible for you to send oscilloscope pictures of the data transaction when reading?"

    I have only very basic logic analyzer, if it works i will send you pictures.

     

    "How fast is your I2C communication? Depending on communication speed, you might be seeing an issue with response time of the bus due to capacitance on the lines." 

     It is 394,971 KHz and i set appropriate register related with 400 kHz transmission.

     

    "Have you tried using smaller resistor values on the I2C pull-ups?"

    Not yet, I will try. 

     

    I show you another chart which makes more visible that this behavior is periodical,  in fact i tried this circuit configuration in two real circuits (with 3 different ADS1115), one more complicated then that shown here and they behave the same way. 

      

  • Lukasz,

    Using a scope you can see if there are issues with transitions from high to low.  ACK has the line low, then releases to high and if the next clock transition and data do not match well due to delays from line capacitance you may have periodic timing issues.  Besides reducing the value of the pull-up resistors, you could try slowing SCL to see if the problem goes away.  A slower clock may give more time for the SDA to settle.

    Best regards,

    Bob B

  • I spend much time to figure out what is happening. I did what You told me. I2C transmission was correct, both on 400 kHz and 100 kHz, with 4,7k and 1k resistors. The problem was (actually still is) with my code. I found some workaround but still I'm curious. It's the weirdest programming issue I have ever met. Could you help me? Maybe you know.

     After sending data to PC (two bytes - one MSB, second LSB of ADC's value) I'm trying to join it into one 16bits variable. I've always done it this way:

    // First shifting msb's bits 8 position to the "left" side of 16 bits variable, then adding first 8 bits of lsb
    value1 = (((unsigned short)msb << 8) + (unsigned short)lsb);

     

    But in the end it behave like I described before. So I did it by shifting every single bit of those two variables to create 16bit value

    // Shifting bit by bit of msb to unsigned short variable - to positions 15-8
    for(int j = 0; j < 8; ++j)
    {
       if(msb & (1 << j))
         value2 |= (1 << (8 + j));
    }

    // Shifting bit by bit of lsb to unsigned short variable - to positions 7-0
    for(int j = 0; j < 8; ++j)
    {
       if(lsb & (1 << j))
         value2 |= (1 << j);
    }

    Do you see any difference between those two ways of doing it? The second one works well.

  • Lukasz,

    The first method loses the sign bit where the second one keeps it.  Other than that, I really don't see a difference.

    Best regards,

    Bob B

  • Thank you for suggestions.