Reading ADS7828E

Hi,

I have some problems reading my ADS7828E ADC with the Arduino over I2C

here is the function I wrote to read the ADC

uint16_t readADC(char sensor){
 const byte DAT[8] = {0x84,0xE4,0xF4,0xD4,0xA4,0xE4,0xB4,0xF4}; // Just using the first byte for the moment
  
  byte highbyte, lowbyte;    
 
    Wire.beginTransmission(ADC7828E_I2C_Adress);
    Wire.write(DAT[sensor]);        
    delay(1);
  if (Wire.endTransmission() == 0){
   //LOG("ADS7828E recognized");
  } else {
     ERR("Failed to recognize ADS7828E");
  }
  delay(1);

uint16_t value;

 Wire.requestFrom(ADC7828E_I2C_Adress, 2);
    while(Wire.available())        
    { 
      
      highbyte = Wire.read();   
      lowbyte = Wire.read();   
          value= ((int)((highbyte<<8) + lowbyte));
     }
  return(value);
}

I connected the REF Pin to my 5,02V supply (clean 5,02V checked with the oscilloscope).

Im confused because I get two different values, depending on how Im calling the function, does anyone know why?

uint16_t adcvalue =0;
for (int i=0; i<1; i++){
    adcvalue +=(readADC(0));
  }
Serial.print("single read FOR:");  
Serial.println(adcvalue);
Serial.print("single read ADC:");
Serial.println(readADC(0));

which gives me

single read ADC:1283
single read FOR:1250
single read ADC:1283
single read FOR:1244
single read ADC:1285
single read FOR:1255
single read ADC:1289
single read FOR:1254

with oversampling it looks like this

uint16_t adcvalue =0;
for (int i=0; i<10; i++){
    adcvalue +=(readADC(0));
  }
Serial.print("oversampling read FOR:");  
Serial.println(adcvalue/10);
oversampling read FOR:1328
single read ADC:1346
oversampling read FOR:1329
single read ADC:1345
oversampling read FOR:1327
single read ADC:1342

The values are pretty constant, depending on the way the function is called but a direct call vs. a call in the for loop, there is a difference of about 10-13 or single shot more than 30! Why?

Also, the value is off by about 16mV, is this normal?

Thanks!

What happens when you swap both input requests (direct first, FOR last)?

I suspect a timing problem, perhaps the transmission is incomplete (aborted due to long delay)?

Here is the best description for my experience with the ADS7828E so far.

Two almost completly the same for loops

Serial.print("first oversampling ADC Value: ");
uint16_t adcvalue =0;
for (int i=0; i<10; i++){
    adcvalue +=(readADC(0));
  }
Serial.println(adcvalue/10);


uint16_t adcvalueuncorr =0;
for (int i=0; i<10; i++){
    adcvalueuncorr +=(readADC(0));
  }
Serial.print("second oversampling ADC Value:");  
Serial.println(adcvalueuncorr/10);

Here is the result:

first oversampling ADC Value: 1319
second oversampling ADC Value:1342
first oversampling ADC Value: 1319
second oversampling ADC Value:1341
first oversampling ADC Value: 1318
second oversampling ADC Value:1341
first oversampling ADC Value: 1319
second oversampling ADC Value:1342
first oversampling ADC Value: 1319
second oversampling ADC Value:1342
first oversampling ADC Value: 1319
second oversampling ADC Value:1341

And the weird thing is, it is always the same! Even if I reset the MCU, the second value is always bigger than the first one.

What if you store 10 (or more) readings in an array, then dump it to Serial?

In readADC I'd check the result of requestFrom (should be 2), to exclude aborted (timed out...) transmissions. I also would discard eventual pending bytes before sending the command, and return immediately and only after reading 2 bytes.

I tweaked my reading function a little bit

  Wire.beginTransmission(ADC7828E_I2C_Adress);
  //Wire.write(DAT[sensor]);        // Configure the device to read each CH
  Wire.write(DAT[sensor]); 
  if (Wire.endTransmission() == 0) { //Checking if the MCP9808 is available
    //LOG("ADS7828E recognized");
  }
    else if (Wire.endTransmission() == 2) { //Checking if the MCP9808 is available
    LOG("ADS7828E data too long to fit in transmit buffer ");}
    else if (Wire.endTransmission() == 2) { //Checking if the MCP9808 is available
    LOG("ADS7828E NACK receifed  on transmit of address ");}
    else if (Wire.endTransmission() == 3) { //Checking if the MCP9808 is available
    LOG("ADS7828E NACK receifed  on transmit of data ");}
    else if (Wire.endTransmission() == 2) { //Checking if the MCP9808 is available
    ERR("Failed to recognize ADS7828E"); }
  uint16_t values;
  // Read A/D value
  Wire.requestFrom(ADC7828E_I2C_Adress, 2);
  byte bytes[2];
  int bytesRead;
  while (2 > Wire.available()) {}
  for (bytesRead = 0;  bytesRead < 2; bytesRead++) {
    bytes[bytesRead] = Wire.read();
  }
  values = (int)((bytes[0]<<8) + bytes[1]);
  return (values);

Calling it like this

 uint16_t adcvalue1[5];
  uint16_t average1 = 0;
  for (int i = 0; i < 5; i++) {
    Serial.print("Channel 1 First Measurement number ");
    Serial.print(i);
    Serial.print(" : ");
    adcvalue1[i] = readADC(0);
    Serial.println(adcvalue1[i]);
    average1 += adcvalue1[i];
  }
  Serial.print("Channel 1 First average: ");
  Serial.println(average1 /5 );

  uint16_t adcvalue2[10];
  uint16_t average2 = 0;
  for (int i = 0; i < 10; i++) {
    Serial.print("Channel 1 Second Measurement number ");
    Serial.print(i);
    Serial.print(" : ");
    adcvalue2[i] = readADC(0);
    Serial.println(adcvalue2[i]);
    average2 += adcvalue2[i];
  }
  Serial.print("Channel 1 Second average: ");
  Serial.println(average2 /10 );
Serial.println("");

But the result still is:

Channel 1 First Measurement number 0 : 1268
Channel 1 First Measurement number 1 : 1289
Channel 1 First Measurement number 2 : 1304
Channel 1 First Measurement number 3 : 1312
Channel 1 First Measurement number 4 : 1317
Channel 1 First average: 1298
Channel 1 Second Measurement number 0 : 1319
Channel 1 Second Measurement number 1 : 1320
Channel 1 Second Measurement number 2 : 1322
Channel 1 Second Measurement number 3 : 1325
Channel 1 Second Measurement number 4 : 1326
Channel 1 Second Measurement number 5 : 1326
Channel 1 Second Measurement number 6 : 1327
Channel 1 Second Measurement number 7 : 1327
Channel 1 Second Measurement number 8 : 1327
Channel 1 Second Measurement number 9 : 1326
Channel 1 Second average: 1324

It looks like the Sensor is not fast enough. Even if I change the swap the loops and commands, it is always the same.

I want to try to read the sensor in HS Mode, but how do I implement this?
you can read it in the datasheet on page 13:
http://www.farnell.com/datasheets/1762476.pdf

Is this pseudocode correct?

Wire.beginTransmission(ADC7828E_I2C_Adress); //Begin Transmission
Wire.write(B00001000); //Send HS Mode Master code
if (Wire.endTransmission() == 3){ LOG("Master mode activated");}
Wire.beginTransmission(B10010000); //Adress with Write Adressing byte at the end
Wire.write(DAT[sensor]); //Sending Command Byte
Wire.endTransmission(); 
Wire.requestFrom(B10010001, 2);  //requesting 2 Bytes to the read adresss
bytes[0] = Wire.read(); // Read byte 1
bytes[1] = Wire.read(); // Read byte 2

Does the Wire library support clock stretching?

Sorry for double Posting but I got a little bit further with my experiments :smiley:

I integrated it like this:

Wire.beginTransmission(ADC7828E_I2C_Adress); //Begin Transmission
Wire.write(B00001000); //Send HS Mode Master code
if (Wire.endTransmission(false) == 3){ LOG("Master mode activated");}
Wire.beginTransmission(B10010000); //Adress with Write Adressing byte at the end
  //Wire.beginTransmission(ADC7828E_I2C_Adress);
  //Wire.write(DAT[sensor]);        // Configure the device to read each CH
  Wire.write(DAT[sensor]); 
  byte endmessage = Wire.endTransmission(false);
  if (endmessage == 0) { //Checking if the MCP9808 is available
    //LOG("ADS7828E recognized");
  }
    else if (endmessage == 1) { //Checking if the MCP9808 is available
    LOG("ADS7828E data too long to fit in transmit buffer ");}
    else if (endmessage == 2) { //Checking if the MCP9808 is available
    LOG("ADS7828E NACK receifed  on transmit of address ");}
    else if (endmessage == 3) { //Checking if the MCP9808 is available
    LOG("ADS7828E NACK receifed  on transmit of data ");}
    else if (endmessage == 2) { //Checking if the MCP9808 is available
    ERR("Failed to recognize ADS7828E"); }
  uint16_t values;
  // Read A/D value
  Wire.requestFrom(ADC7828E_I2C_Adress, 2);
  byte bytes[2];
  int bytesRead;
  while (2 > Wire.available()) {}
  for (bytesRead = 0;  bytesRead < 2; bytesRead++) {
    bytes[bytesRead] = Wire.read();
  }
  values = (int)((bytes[0]<<8) + bytes[1]);
  return (values);
}

Now, the console output is the following :smiley:

Channel 1 First Measurement number 0 : ssertion "(address & 0x80) == 0" failed: file "../source/twi.c", line 271, function: TWI_StartWrite
Exiting with status 1.

EDIT: The error above was resolved by changing the B00… Adress to the normal Adress. I changed it to B00… since I thought I had to edit the Read/Write byte myself, but I hope it is done by the Wire Library (couldnt find a doc which states how beginTransmission( and requestFrom( work).

But normally I should receive a NACK after writing the HS mode code, which I dont. Looks like the ADS7828E didnt switch to HS Mode (?).

The Wire library shifts the given 7 bit address, and inserts the R/W bit.

NACK (Negative ACKnowledge) indicates an slave error, you never should get it.

Eventually use switch to decode the error code, you check twice for ==2.

You also can check requestFrom, should return 2, and if so read the 2 bytes received.