|
|
View previous topic :: View next topic |
Author |
Message |
joseph20480
Joined: 21 Dec 2011 Posts: 42
|
ADS1115 CAN16 bits driver - delay !? |
Posted: Wed Feb 22, 2017 10:39 am |
|
|
hi,
I'm currently write an library for the ADS1115 (Family of ADS1113/4/5).
It's an i2C 16 bits sigma delta.
My library works... i'm able to write into register, read register, configure the chip and have the result of the conversion. But, if i want to change somethings into the register (like change the input pin), i have to wait at least 25ms before read the new conversion result...
I have read different library for this chip for Arduino and i have never see that ... if you have an idea...
Code: |
ADS1115_write(addr_1, configuration_register, ADS1115_OS_MASK + ADS1115_MUX_SINGLE_0 + ADS1115_PGA_2_048V + ADS1115_MODE_CONTIN + ADS1115_RATE_64SPS + ADS1115_disable_comparator);
|
Code: |
//----------------------------------
byte ADS1115_ready(int8 addr)
{
byte ack;
i2c_start();
ack=i2c_write(addr+write_bit);
i2c_stop();
return !ack;
}
//----------------------------------
|
Code: |
//----------------------------------
void ads1115_write(int8 addr,int8 reg,int16 data)
{
int8 lo,hi;
lo=data;
hi=data>>8;
i2c_start();
i2c_write(addr + write_bit); // Address
i2c_write(reg); // Config register
i2c_write(hi);
i2c_write(lo);
i2c_stop();
}
//----------------------------------
|
Code: |
//----------------------------------
int16 ads1115_read(int8 addr,int8 reg)
{
int16 data;
i2c_start();
i2c_write(addr + write_bit);
i2c_write(reg);
i2c_stop();
i2c_start();
i2c_write(addr + read_bit);
data=i2c_read(1);
data=data<<8;
data=data+i2c_read(1);
i2c_stop();
return data;
}
//----------------------------------
|
Code: |
//----------------------------------
int16 ADS1115_raw_measure(int8 addr,int8 channel)
{
int16 mesure;
int16 registre;
registre=ADS1115_read(addr,configuration_register);
registre = registre & 0b1000111111111111;
if (channel==0){registre=registre | ADS1115_MUX_SINGLE_0;}
if (channel==1){registre=registre | ADS1115_MUX_SINGLE_1;}
if (channel==2){registre=registre | ADS1115_MUX_SINGLE_2;}
if (channel==3){registre=registre | ADS1115_MUX_SINGLE_3;}
ADS1115_write(addr,configuration_register,registre);
[b] delay_ms(25); //...... Delay !???!!! [/b]
mesure=ADS1115_read(addr,convertion_register);
return mesure;
}
//-----------------------------------
|
The problem appears when i ask measure on every channel (begin by ch1, ch2, ch3, ch4) :
WITH delay : normal operation, the result of conversion is good.
Without delay : it's seem that the mux into the chip have not change... i try to measure the channel two, but the chip send me the value of channel 1. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Wed Feb 22, 2017 11:16 am |
|
|
I see that chip has two modes, single or continuous . My guess is that you've set it for 'single' reading mode which automaticly 'powers down' to save energy.
You should printout the actual 'configuration' bits to confirm their settings.
It may not be what the problem is , but should be looked at.
Jay |
|
|
joseph20480
Joined: 21 Dec 2011 Posts: 42
|
|
Posted: Thu Feb 23, 2017 2:15 am |
|
|
temtronic wrote: | I see that chip has two modes, single or continuous . My guess is that you've set it for 'single' reading mode which automaticly 'powers down' to save energy.
You should printout the actual 'configuration' bits to confirm their settings.
It may not be what the problem is, but should be looked at.
Jay |
Thanks for your reply but the register sended seems to be correct.
The conversion mode is set to 0 for "continuous-conversion
mode" - page26 from data sheet.
No further remarks ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Feb 23, 2017 3:04 am |
|
|
joseph20480 wrote: | No further remarks ? |
Quote: | ADS1115_OS_MASK + ADS1115_MUX_SINGLE_0 + ADS1115_PGA_2_048V + ADS1115_MODE_CONTIN + ADS1115_RATE_64SPS + ADS1115 |
Post the #define statements for all these constants, and any other
constants that refer to the ads1115.
Post your PIC.
Post your CCS compiler version.
Post your #fuses and your #use delay(), etc.
And I think temtronic is suggesting that you try Single shot mode
instead of continuous conversion mode. See what happens.
And also, post an actual test program. That's why I didn't initially reply.
For example, you have the ADS1115_ready() function, but it is not called
in your posted code snippets. What are you really doing in your program ?
We won't know, until you post a test program. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu Feb 23, 2017 3:34 am |
|
|
You do realise the ADS1115 is a delta-sigma ADC don't you? It works by massive oversampling and with heavy digital filtration. They have slow update rates; the ADS1115 going at its fastest at 860samples/second.
Depending on how you have configured it, it will take at least one full sample time to produce an new result after any change. A delay of 25ms imples that the actual sample rate is no more than 40sps, which is entirely plausible for this ADC.
That you get the result of the last conversion until a new converson is complete is also understandable. In short, it appears this convertor is behaving much as I, and you, should expect it to. They are at their best when sampling single, small, slowly-changing signals with high precision but long latency, for things such as load cells, thermocouples, thermistors/PRTs, battery voltages and the like. They are not at their best, or at least are very slow, when used by switching frequently between mulitple signals. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Thu Feb 23, 2017 4:20 am |
|
|
The standard Arduino code for this chip, loops continuously, until it sees bit 7 of the first byte read go 'high' to say a conversion has completed.
The normal Arduino routine is effectively:
Code: |
int8 msb, lsb;
do
{
i2c_start();
i2c_write(addr + read_bit);
msb=i2c_read(0);
lsb=2c_read(1);
i2c_stop();
} while (bit_test(msb,7)==0);
data = make16(msb & 0x7F, lsb);
|
So it doesn't wait before triggering this, it keeps repeating the read, until the flag sets to say the conversion has completed. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
joseph20480
Joined: 21 Dec 2011 Posts: 42
|
|
Posted: Fri Feb 24, 2017 3:36 am |
|
|
Thanks to Ttelmah and PCM programmer, you have right !
I had two errors in code/mind.
The first was that I didn't test if the CAN have finished to convert before read the result... the code from Ttelmah work very well.
The second is about the technology and how work an ADC. Very interesting.
Thanks every one ! |
|
|
vasiliok
Joined: 17 May 2011 Posts: 19 Location: Kaunas, Lithuania
|
|
Posted: Wed Jun 16, 2021 12:30 am |
|
|
I have completed a bit the code of topic starter comrade joseph20480
Code: |
#define address1 0x90 // first ADC module
#define address2 0x92 // second ADC module (if you have one?)
#define write_bit 0
#define read_bit 1
#define configuration_register 0x01
#define convertion_register 0x00
#define ADS1115_MUX_SINGLE_0 0b0100000000000000
#define ADS1115_MUX_SINGLE_1 0b0101000000000000
#define ADS1115_MUX_SINGLE_2 0b0110000000000000
#define ADS1115_MUX_SINGLE_3 0b0111000000000000
//-----------------------------------------------------------
byte ADS1115_ready(int8 addr)
{
byte ack;
i2c_start();
ack=i2c_write(addr+write_bit);
i2c_stop();
return !ack;
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void ads1115_write(int8 addr,int8 reg,int16 data)
{
int8 lo,hi;
lo=data;
hi=data>>8;
i2c_start();
i2c_write(addr + write_bit); // Address
i2c_write(reg); // Config register
i2c_write(hi);
i2c_write(lo);
i2c_stop();
}
//-----------------------------------------------------------
//-----------------------------------------------------------
int16 ads1115_read(int8 addr,int8 reg)
{
int16 data;
i2c_start();
i2c_write(addr + write_bit);
i2c_write(reg);
i2c_stop();
i2c_start();
i2c_write(addr + read_bit);
data=i2c_read(1);
data=data<<8;
data=data+i2c_read(1);
i2c_stop();
return data;
}
//-----------------------------------------------------------
//-----------------------------------------------------------
int16 ADS1115_raw_measure(int8 addr,int8 channel)
{
unsigned int16 mesure;
unsigned int16 registre=0;
//registre &= 0b1000001100011111;
if (channel==0){registre=registre | ADS1115_MUX_SINGLE_0;}
if (channel==1){registre=registre | ADS1115_MUX_SINGLE_1;}
if (channel==2){registre=registre | ADS1115_MUX_SINGLE_2;}
if (channel==3){registre=registre | ADS1115_MUX_SINGLE_3;}
ADS1115_write(addr, configuration_register, registre);
delay_ms(280); //For data rate of 8 SPS, maximum time = 2*(1/(0.9*SPS) = 277mS delay
mesure = ADS1115_read(addr, convertion_register);
//mesure = ADS1115_read(addr, convertion_register);
return mesure;
}
//----------------------------------------------------------- |
And the main code where I read ch1, ch2, ch3 of my first ADC module (I have two modules in the circuit).
Read three channels and show values on LCD screen.
MCU is PIC24FV32KA304
Maybe this code will help someone
Code: | while(TRUE){
resultas = ADS1115_raw_measure(address1, 1);
itampa1 = 0.00133 * (float)resultas;
lcd_gotoxy(1,1);
//printf(lcd_putc, "%Lu ", resultas);
printf(lcd_putc, "ch1 %2.1f ", itampa1);
delay_ms(1500);
resultas = ADS1115_raw_measure(address1, 2);
itampa2 = 0.00133 * (float)resultas;
lcd_gotoxy(1,1);
//printf(lcd_putc, "%Lu ", resultas);
printf(lcd_putc, "ch2 %2.1f ", itampa2);
delay_ms(1500);
resultas = ADS1115_raw_measure(address1, 3);
itampa3 = 0.00133 * (float)resultas;
lcd_gotoxy(1,1);
//printf(lcd_putc, "%Lu ", resultas);
printf(lcd_putc, "ch3 %2.1f ", itampa3);
delay_ms(1500);
}//WHILE
}//MAIN |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Wed Jun 16, 2021 2:28 am |
|
|
Thanks vasiliok. Nice to have somebody post a potential termination to the
thread.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|