I am having some strange issues when using my ADS1015 in single ended mode with an arduino uno. I have the ADC wired up to my arduino using I2C and powered by 5 volts. I have changed the values in the registers to accept up to 6.144V. I am using an ADXL335 accelerometer as my input to the ADC.
I have had this issue where when i change the orientation of the accelerometer, more than one of the inputs changes at once. i have attached a .txt file as an example of what is happening (the 1st column is not connected to the acceleromter, 2nd, 3rd and 4th are. 2nd is X, 3rd is Y, 4th is Z). The data wouldn't paste properly on here, hence the file
The strange thing is that when i use the ADS1115's i have, there is no problem at all. I did have tro introduce a 5ms delay into the loop to stop the same thing happening with the ADS1115 which i'm not thrilled about. I have tried different boards, accelerometers, wiring, adding a power supply rather than just the usb cable, breadboard and as said above different ADC's. but it is only ever a problem with the ADS1015.
Anybody have any ideas? I've found threads regarding this but none of them have helped apart from adding the delay in the loop which helped with the 1115. Below is my code;
/*
Read pot on AIN1 convert value to voltage
then display on Arduino serial monitor.
By Lewis Loflin lewis@bvu.net
http://www.sullivan-county.com/main.htm
Electronics website:
http://www.bristolwatch.com/index.htm
*/
#include <Wire.h> // specify use of Wire.h library
#define ASD1115 0x48
unsigned int val = 0;
unsigned int val_1 = 0;
unsigned int val_2 = 0;
unsigned int val_3 = 0;
unsigned int val_4 = 0;
int storage_buffer[4];
byte writeBuf[6];
byte buffer[3];
float t_micro;
void setup() {
Serial.begin(115200);
//while(!SerialUSB);
Wire.begin(); // begin I2C
// ASD1115
// set config register and start conversion
// ANC1 and GND, 4.096v, 128s/
writeBuf[0] = 1; // config register is 1
//writeBuf[1] = 0b11010000; // 0xC2 single shot off <== NEW - single conversion/ AIN1 & GND/ 6.144V/ Continuous (0)
//writeBuf[1] = 0b11110010; // 0xC2 single shot off <== ORIGINAL - single conversion/ AIN1 & GND/ 4.096V/ Continuous (0)
writeBuf[1] = 0b11000000; // 0xC2 single shot off <== NEW - single conversion/ AIN0 & GND/ 6.144V/ Continuous (0)
writeBuf[2] = 0b11010000; // 0xC2 single shot off <== NEW - single conversion/ AIN1 & GND/ 6.144V/ Continuous (0)
writeBuf[3] = 0b11100000; // 0xC2 single shot off <== NEW - single conversion/ AIN2 & GND/ 6.144V/ Continuous (0)
writeBuf[4] = 0b11110000; // 0xC2 single shot off <== NEW - single conversion/ AIN3 & GND/ 6.144V/ Continuous (0)
// bit 15 flag bit for single shot
// Bits 14-12 input selection:
// 100 ANC0; 101 ANC1; 110 ANC2; 111 ANC3
// Bits 11-9 Amp gain. Default to 010 here 001 P19
// Bit 8 Operational mode of the ADS1115.
// 0 : Continuous conversion mode
// 1 : Power-down single-shot mode (default)
//writeBuf[2] = 0b10000101; // bits 7-0 0x85 //8 SPS
//writeBuf[2] = 0b10000101; // bits 7-0 0x85 //128 SPS
writeBuf[5] = 0b11100101; // bits 7-0 0x85 //860 SPS
// Bits 7-5 data rate default to 100 for 128SPS
// Bits 4-0 comparator functions see spec sheet.
// setup ADS1115
Wire.beginTransmission(ASD1115); // ADC
Wire.write(writeBuf[0]);
Wire.write(writeBuf[1]);
Wire.write(writeBuf[5]);
Wire.endTransmission();
delay(500);
} // end setup
void loop() {
for (int i = 1; i <= 4; i++)
{
// setup ADS1115
Wire.beginTransmission(ASD1115); // ADC
Wire.write(writeBuf[0]);
Wire.write(writeBuf[i]);
Wire.write(writeBuf[5]);
Wire.endTransmission();
buffer[0] = 0; // pointer
Wire.beginTransmission(ASD1115); // DAC
Wire.write(buffer[0]); // pointer
Wire.endTransmission();
Wire.requestFrom(ASD1115, 2);
buffer[1] = Wire.read(); //
buffer[2] = Wire.read(); //
Wire.endTransmission();
val = buffer[1] << 8 | buffer[2];
storage_buffer[i-1] = val;
//Serial.println(val);
delay(5);
}
//======================================
Serial.print(storage_buffer[0]);
Serial.print("\t");
Serial.print(storage_buffer[1]);
Serial.print("\t");
Serial.print(storage_buffer[2]);
Serial.print("\t");
Serial.println(storage_buffer[3]);
}
/*
// convert display results
val_1 = buffer[1] << 8 | buffer[5];
val_2 = buffer[2] << 8 | buffer[5];
val_3 = buffer[3] << 8 | buffer[5];
val_4 = buffer[4] << 8 | buffer[5];
t_micro = micros();
// if (val > 32768) val = 0;
Serial.print(t_micro/1000000.0,6);
Serial.print("\t");
Serial.print(val_1);
Serial.print("\t");
Serial.print(val_2);
Serial.print("\t");
Serial.print(val_3);
Serial.print("\t");
Serial.println(val_4);
} // end loop
*/
[code]
Thanks
Ross
Ross46:
I have changed the values in the registers to accept up to 6.144V. I am using an ADXL335 accelerometer as my input to the ADC.
Why.
The ADS can't accept more than 5volt anyway in 6.144volt (PGA2/3) mode,
and the ADXL335 can't output more than ~2.8volt.
With PGA2/3 you're loosing a full bit of resolution.
PGA1 (4.096volt) seems more locigal for a 3.3volt device.
But if it was me, I would use PGA2 (2.048volt), with suitable load resistors (150k) to drop that ~2.8volt to 2.048volt.
(the ADXL has a 32k output impedance, use it.)
Leo..
from what i could find, if your using a 5V device, you cant use the 1x gain setting. or have i misinterpreted that? so if i set it as 4.096V, as the ADXL335 can't output more than 2.8V it's safe to use the 1x setting?
i'll look into using the resistors in 2.048V mode.
would the above cause the issues of interference across channels? As that has me completely stumped as for the reason, including why the delay stops it
If you use a different PGA gain, then max A/D value is reached at that voltage.
You still can input 0-5volt if the ADS is powered with 5volt.
It just results in the A/D outputting max value.
You can never input 6.144volt, because max input voltage is 5volt on a 5volt supply.
So you never can reach max A/D value on the default PGA setting.
Same if you power the ADS from 3.3volt.
Max input voltage is then 3.3volt, and you can never reach max A/D values on the 4.096volt PGA setting.
Not sure about the code (semi-noob there).
I think most are using the Adafruit library.
Leo..
I might use the adafruit library at a later stage but at the moment i'm trying to learn to use registers on devices as i've just bought an MPU9250 which will i will need to access the registers on. Also sorry for the messy code, had forgotten how much i had commented out to change certain aspects.
Where you are talking about using the PGA to get the maximum A/D values. Could this have an effect on the other channels if done incorrectly?
My ADS1115 code works with a delay (though i'm trying to get round that), although without i have the same issue as with the ADS1015. Do you know what could cause the channels to interfere with each other? Is this down to how the MUX works internally or do i have a dud chip?
#include <Wire.h> // specify use of Wire.h library
#define ASD1115 0x48
unsigned int val = 0;
int storage_buffer[4];
byte writeBuf[6];
byte buffer[3];
float t_micro;
void setup() {
Serial.begin(115200);
Wire.begin(); // begin I2C
Wire.setClock(400000);
// ASD1115
// set config register and start conversion
writeBuf[0] = 1; // config register is 1
writeBuf[1] = 0b11000000; // 0xC2 single shot off - single conversion/ AIN0 & GND/ 6.144V/ Continuous (0)
writeBuf[2] = 0b11010000; // 0xC2 single shot off - single conversion/ AIN1 & GND/ 6.144V/ Continuous (0)
writeBuf[3] = 0b11100000; // 0xC2 single shot off - single conversion/ AIN2 & GND/ 6.144V/ Continuous (0)
writeBuf[4] = 0b11110000; // 0xC2 single shot off - single conversion/ AIN3 & GND/ 6.144V/ Continuous (0)
// bit 15 flag bit for single shot
// Bits 14-12 input selection:
// 100 ANC0; 101 ANC1; 110 ANC2; 111 ANC3
// Bits 11-9 Amp gain. Default to 010 here 000 P19
// Bit 8 Operational mode of the ADS1115.
// 0 : Continuous conversion mode
// 1 : Power-down single-shot mode (default)
writeBuf[5] = 0b11100101; // bits 7-0 0x85 //860 SPS, comparator = traditional,
//polarity = active low, latching, assert after two conversions
// Bits 7-5 data rate default to 100 for 128SPS, here 111 = 860SPS
// Bits 4-0 comparator functions see spec sheet.
// setup ADS1115
Wire.beginTransmission(ASD1115); // ADC
Wire.write(writeBuf[0]);
Wire.write(writeBuf[1]);
Wire.write(writeBuf[5]);
Wire.endTransmission();
delay(500);
} // end setup
void loop() {
for (int i = 1; i <= 4; i++)
{
// setup ADS1115
Wire.beginTransmission(ASD1115); // ADC
Wire.write(writeBuf[0]);
Wire.write(writeBuf[i]);
Wire.write(writeBuf[5]);
Wire.endTransmission();
buffer[0] = 0; // pointer
Wire.beginTransmission(ASD1115); // DAC
Wire.write(buffer[0]); // pointer
Wire.endTransmission();
Wire.requestFrom(ASD1115, 2);
buffer[1] = Wire.read(); //
buffer[2] = Wire.read(); //
Wire.endTransmission();
val = buffer[1] << 8 | buffer[2];
storage_buffer[i-1] = val;
//delay(10);
}
//======================================
t_micro = micros();
Serial.print(t_micro/1000000.0,6);
Serial.print("\t");
Serial.print(storage_buffer[0]);
Serial.print("\t");
Serial.print(storage_buffer[1]);
Serial.print("\t");
Serial.print(storage_buffer[2]);
Serial.print("\t");
Serial.println(storage_buffer[3]);
}
Don't know about cross-talk in an ADS, but it's common knowledge in the A/D of an Arduino.
When you switch A/D channel, and the output impedance of whatever you're measuriing is too high, then you could have some 'ghost charge' left from the previous channel.
Various solutions.
small (10-100n) caps from each A/D input to ground (the sensor might already have them).
two consecutive readings (only second value being used).
Delays do nothing else than...delay.
Leo..
I've now managed to get up to 250Hz without interference. Much better than the 80 or so i wasgetting before with problems. The main change is using interrupts rather than just polling randomly! This still uses a slight delay, but that is because the ADXL335 can only work at up to 550Hz on the Z axis and dropping the delay any further goes past that limit. Thankyou everyone for your help.
For anyone else reading this, mysetup and what i've learned/ used are below;
ADS1015 at 3300 SPS
ADXL335 accelerometer
Arduino Due using native USB
register settings;
bit 15 - 1 - start a single conversion
bit 14:12 - 100/101/110/111 - all bits for AIN(x) to ground
bit 11:9 - 001 - +/- 4.096V
bit 8 - 1 - single shot
bit 7:5 - 111 - 3300 SPS
bit 4 - 0 - Traditional comparator
bit 3 - 0 - Active low
bit 2 - 0 - non latching comparator
bit 1:0 - 00 - assert after one conversion
other settings/ lessons for myself
to use the native USB, all serial.prints become serialUSB.print. the line for Serial.begin stays, but underneath you have to write SerialUSB.begin and while(!SerialUSB)
Serial.begin(2000000);
SerialUSB.begin(2000000);
while(!SerialUSB);
SerialUSB.print("whatever you want to print");
The I2C bus speed didn't seem to be fast enough to support this data rate, that could have been down to continuous polling as i haven't tested that, but it seems (someone correct me if i'm wrong please) that writing bus speed can be changed with;
Wire.setClock(400000);
which is useful to know.
So yeah, thanks to all that helped (mainly you Wawa, but others have on other posts and forums so don't want to forget anyone)