RobTillaart / ADS1X15

Arduino library for ADS1015 = I2C 12 bit ADC and ADS1115 = I2C 16 bit ADC
MIT License
155 stars 29 forks source link

Read 4 channel asynchronous #24

Closed Mplex72 closed 3 years ago

Mplex72 commented 3 years ago

Hi ,

How can I read 4 channels asynchronus ? The problem is the readout for each value see line below ;

 int16_t value = ADS.getValue(i); 

and gives the following error ; "invalid types 'int16_t {aka int}[int]' "

I have the followiing sketch to test ;


//

#include "ADS1X15.h"

ADS1115 ADS(0x48);
float f = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(0);
  f = ADS.toVoltage();      // voltage factor
  ADS.requestADC(0);
}

void loop()
{
  if (ADS.isBusy() == false)
  {
    for (int i = 0; i < 4; i++) {
      int16_t value = ADS.getValue(i);
      ADS.requestADC(i);  // request a new one
      Serial.print("\tAnalog0: ");
      Serial.print(value[i]);
      Serial.print('\t');
      Serial.println(value[i] * f, 3);
    }
  }
  // simulate other tasks...
  delay(2000);
}

// -- END OF FILE --

Klass

RobTillaart commented 3 years ago

Hi Klass,

which platform do you use? which version of the library?

Think you must remove the parameter i from the next line.

 int16_t value = ADS.getValue();
Mplex72 commented 3 years ago

Hi Rob,

I,m using Arduino 1.8.15 and your lastest ADS1115 lib Compile for arduino Pro mini.

Now it,s accepted in the compiler ,

The question is now ; I suppose it will get data blocks with the 4 data values the correct order ,but have to test it now.

first i = (value1) for the first channel to fourth i = ((value4)) for the fourth channel

and also at the correct timing (all 4 within 3 millis would be good enough)

Regards, Klass


`//

include "ADS1X15.h"

int16_t value[4] = { 0, 0, 0, 0 };

ADS1115 ADS(0x48); float f = 0;

void setup() { Serial.begin(115200); Serial.println(FILE); Serial.print("ADS1X15_LIB_VERSION: "); Serial.println(ADS1X15_LIB_VERSION);

ADS.begin(); ADS.setGain(0); f = ADS.toVoltage(); // voltage factor ADS.requestADC(0); }

void loop() { if (ADS.isBusy() == false) { for (int i = 0; i < 4; i++) { value[i] = ADS.getValue(); ADS.requestADC(i); // request a new one Serial.print("\tAnalog0: "); Serial.print(value[i]); Serial.print('\t'); Serial.println(value[i] * f, 3); } } // simulate other tasks... delay(500); }

// -- END OF FILE --`

RobTillaart commented 3 years ago

array indices are counted from 0 to n-1 in C/C++ so in this program from 0..3

int16_t value[4] will have value[0] for the first channel, ... value[3] for the fourth channel

The async methods are implemented because reading an ADC sensor takes substantial time (read datasheet for details. To understand the proper usage you should have a look at

https://github.com/RobTillaart/ADS1X15/blob/master/examples/ADS_continuous_4_channel/ADS_continuous_4_channel.ino which shows how to read 4 channels as fast as possible .

Your example does request a next sample before it even checks if ADS.isBusy() == false that must be done after every request

Mplex72 commented 3 years ago

Have changed the sketch quite a bit, How can I get the sketch to read the four channels as fast as possible and THEN wait a second ? now it waits a second after each sample.

//

#include "ADS1X15.h"

ADS1115 ADS(0x48);
float f = 0;
uint8_t channel = 0;
int16_t val[4] = { 0, 0, 0, 0 };

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(0);
  ADS.setDataRate(3);
  f = ADS.toVoltage();      // voltage factor

  for (int i = 0; i < 4; i++)
  {
    ADS.requestADC(i);
  }
}

void loop()
{
//  handleConversion();
{
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val[i]);
    Serial.print('\t');
    handleConversion();
  }
  Serial.println();
}
  delay(1000);
}

void handleConversion()
{
  if (ADS.isBusy() == false)
  {
    // save the value
    val[channel] = ADS.getValue();
    // request next channel
    channel++;
    if (channel >= 4) channel = 0;
    ADS.requestADC(channel);
  }
}

// -- END OF FILE --
RobTillaart commented 3 years ago

I updated your code tags so the code syntax is highlighted. (edit your post to see how it is done)

If you just want to read 4 channels and then wait for a second you do not need async calls.

something like this should be sufficient, (not tested)


#include "ADS1X15.h"

ADS1115 ADS(0x48);
float f = 0;
uint8_t channel = 0;
int16_t val[4] = { 0, 0, 0, 0 };

uint32_t lastTime = 0, now = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS.begin();
  ADS.setGain(0);
  ADS.setDataRate(3);
  f = ADS.toVoltage();      // voltage factor
}

void loop()
{
  now = millis();
  if (now - lastTime >= 1000)
  {
    lastTime = now;
    for (int i = 0; i < 4; i++)
    {
      val[i] = ADS.readADC(i);
      Serial.print('\t');
      Serial.print(val[i]);
    }
    Serial.println();
  }

}
RobTillaart commented 3 years ago

Solved?

Mplex72 commented 3 years ago

I,m still strugling to get 4 channels properly working . It looked so nice to let the adc1115 do his job at the background while the arduino is processing other sensors data.

I think I have to go back to the continues reading option and close this . Thanks for the thelp Klass

RobTillaart commented 3 years ago

If you can post your complete sketch I can have a quick look how to maximize throughput.

Which platform do you use?

Mplex72 commented 3 years ago

Hi , I use Arduino Pro Mini with CANbus but I can upgrade to Teensy The following sketch uses 2 ADC units. target is to use 4 modules and output 16 channels at 100hz but the code seems not fast enough. I use a small capacitor over the analog inputs to smooth it a bit. would prefer software averaging but that gives a lot more overhead. I suppose the 128Hz speed on the adc is enough for this setup ?

#include "ADS1X15.h"
#include <elapsedMillis.h>

#include <mcp_can.h>
#include <SPI.h>

elapsedMillis ADSmillis1;

MCP_CAN CAN0(10);     // Set CS to pin 10

ADS1115 ADS0(0x48);
ADS1115 ADS1(0x49);

uint8_t channel = 0;
int16_t val[4] = { 0, 0, 0, 0 };

uint32_t lastTime = 0, now = 0;

void ADS0_read() {
  byte stmp[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

  for (int i = 0; i < 4; i++)
  {
    val[i] = (ADS0.readADC(i) * 0.1875);
    Serial.print('\t');
    Serial.print(val[i]);
    stmp[ i * 2] = val[i] / 256;
    stmp[ i * 2 + 1] = val[i] % 256;
    // send data:  id = 0x70, standard frame, data len = 8, stmp: data buf
    CAN0.sendMsgBuf(0x70, 0, 8, stmp);
  }
  Serial.println();
}

void ADS1_read() {
  byte stmp[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

  for (int i = 0; i < 4; i++)
  {
    val[i] = (ADS1.readADC(i) * 0.1875);
    Serial.print('\t');
    Serial.print(val[i]);
    stmp[ i * 2] = val[i] / 256;
    stmp[ i * 2 + 1] = val[i] % 256;
    // send data:  id = 0x70, standard frame, data len = 8, stmp: data buf
    CAN0.sendMsgBuf(0x71, 0, 8, stmp);
  }
  Serial.println();
}

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) Serial.println("MCP2515 Initialized Successfully!");
  else Serial.println("Error Initializing MCP2515...");

  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted

  ADS0.begin();
  ADS0.setGain(0);
  ADS0.setDataRate(4);

  ADS1.begin();
  ADS1.setGain(0);
  ADS1.setDataRate(4);
}

void loop()
{
  if (ADSmillis1 >= 1000)
  {
    ADS0_read();
  }
  if (ADSmillis1 >= 1100)
  {
    ADS1_read();
    ADSmillis1 = ADSmillis1 - 200;
  }
}
RobTillaart commented 3 years ago

Saw the code, I'll look at it tonight

RobTillaart commented 3 years ago

have a look at this (could not compile as I do not have all libraries.

what I did is read the ADS channels in pairs / parrallel if all pairs are collected, I print them and then I send them wait for a second, request new pairs.

It is using the async interface as that allows me to request ADS1 right after ADS0 is started, so they work effectively in parallel.

At least this way you can sample multiple ADS in parallel.

#include "ADS1X15.h"
// #include <elapsedMillis.h>

#include <mcp_can.h>
#include <SPI.h>

// elapsedMillis ADSmillis1;

MCP_CAN CAN0(10);     // Set CS to pin 10

ADS1115 ADS0(0x48);
ADS1115 ADS1(0x49);

uint8_t channel = 0;
int16_t val0[4] = { 0, 0, 0, 0 };
int16_t val1[4] = { 0, 0, 0, 0 };
int     idx = 0;

uint32_t lastTime = 0, now = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) 
  {
    Serial.println("MCP2515 CAN0 Initialized Successfully!");
  }
  else Serial.println("Error Initializing MCP2515...");
  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted

  ADS0.begin();
  ADS0.setGain(0);
  ADS0.setDataRate(4);

  ADS1.begin();
  ADS1.setGain(0);
  ADS1.setDataRate(4);

  ADS_request_all();
}

void loop()
{
  while (ADS_read_all();  // we need to continue sampling.

  // we have all 8 values
  ADS_print_all();
  ADS_send_all();
  delay(1000);      // wait a second.
  ADS_request();
}

void ADS_request_all()
{
  ADS0.requestADC(idx);
  ADS1.requestADC(idx);
}

bool ADS_read_all() 
{
  // if both ADS are ready
  if ((ADS0.isBusy() == false) && (ADS1.isBusy() == false))
  {
    val0[idx] = ADS0.getValue(idx) * 0.1875;
    val1[idx] = ADS1.getValue(idx) * 0.1875;
    idx++;
    if (idx < 4)
    {
      ADS0.requestADC(idx);
      ADS1.requestADC(idx);
      return true;
    }
    return false;
  }
  return true; 
}

void ADS_print_all()
{
  // TIMESTAMP
  // Serial.print(millis());
  // Serial.print("\t");
  // PRINT ALL VALUES OF ADC0
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val0[i]);
    Serial.print("\t");
  }
  // PRINT ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val1[i]);
    Serial.print("\t");
  }
  Serial.println();
}

void ADS_send_all()
{
  // SEND ALL VALUES OF ADC0
  byte stmp[8];
  for (int i = 0; i < 4; i++)
  {
    stmp[ i * 2] = val0[i] / 256;
    stmp[ i * 2 + 1] = val0[i] % 256;
    CAN0.sendMsgBuf(0x70, 0, 8, stmp);
  }
  // SEND ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    stmp[ i * 2] = val1[i] / 256;
    stmp[ i * 2 + 1] = val1[i] % 256;
    CAN0.sendMsgBuf(0x71, 0, 8, stmp);
  }
}

you need to reset idx to 0; somewhere

Mplex72 commented 3 years ago

Wauw , complete different view on it , looking good. This should be working ; strange problem at line 75 see comment; no matching function for call to 'ADS1115::getValue(int&)' following the sketch , ADS1 is setup and started ? no error on the ADS1 request but then .....

Documents\Arduino\libraries\ADS1X15-master/ADS1X15.h:74:12: note: candidate expects 0 arguments, 1 provided ADS1115_8ch_CAN_06:75:34: error: no matching function for call to 'ADS1115::getValue(int&)' val1[idx] = ADS1.getValue(idx) * 0.1875;


#include "ADS1X15.h"
// #include <elapsedMillis.h>

#include <mcp_can.h>
#include <SPI.h>

// elapsedMillis ADSmillis1;

MCP_CAN CAN0(10);     // Set CS to pin 10

ADS1115 ADS0(0x48);
ADS1115 ADS1(0x49);

uint8_t channel = 0;
int16_t val0[4] = { 0, 0, 0, 0 };
int16_t val1[4] = { 0, 0, 0, 0 };
int     idx = 0;

uint32_t lastTime = 0, now = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) 
  {
    Serial.println("MCP2515 CAN0 Initialized Successfully!");
  }
  else Serial.println("Error Initializing MCP2515...");
  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted

  ADS0.begin();
  ADS0.setGain(0);
  ADS0.setDataRate(4);

  ADS1.begin();
  ADS1.setGain(0);
  ADS1.setDataRate(4);

  ADS_request_all();
}

void loop()
{
  while (ADS_read_all());  // we need to continue sampling.

  // we have all 8 values
  ADS_print_all();
  ADS_send_all();
  delay(1000);      // wait a second.
  ADS_request_all();
}

void ADS_request_all()
{
  ADS0.requestADC(idx);
  ADS1.requestADC(idx);
}

bool ADS_read_all() 
{
  // if both ADS are ready
  if ((ADS0.isBusy() == false) && (ADS1.isBusy() == false))
  {
    val0[idx] = ADS0.getValue(idx) * 0.1875;
    val1[idx] = ADS1.getValue(idx) * 0.1875;       // _**line 75 error  ;  no matching function for call to 'ADS1115::getValue(int&)'**_
    idx++;
    if (idx < 4)
    {
      ADS0.requestADC(idx);
      ADS1.requestADC(idx);
      return true;
    }
    return false;
  }
  return true; 
}

void ADS_print_all()
{
  // TIMESTAMP
  // Serial.print(millis());
  // Serial.print("\t");
  // PRINT ALL VALUES OF ADC0
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val0[i]);
    Serial.print("\t");
  }
  // PRINT ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val1[i]);
    Serial.print("\t");
  }
  Serial.println();
}

void ADS_send_all()
{
  // SEND ALL VALUES OF ADC0
  byte stmp[8];
  for (int i = 0; i < 4; i++)
  {
    stmp[ i * 2] = val0[i] / 256;
    stmp[ i * 2 + 1] = val0[i] % 256;
    CAN0.sendMsgBuf(0x70, 0, 8, stmp);
  }
  // SEND ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    stmp[ i * 2] = val1[i] / 256;
    stmp[ i * 2 + 1] = val1[i] % 256;
    CAN0.sendMsgBuf(0x71, 0, 8, stmp);
  }
}

1. 

> 
> 
> > Here it is;
> > https://github.com/coryjfowler/MCP_CAN_lib
> 
> Is not supported in the library manager of the IDE unfortunately .

> 
> 
> > Here it is;
> > https://github.com/coryjfowler/MCP_CAN_lib
> 
> Is not supported in the library manager of the IDE unfortunately .

Wich one should it be ? for eventually better results ?
RobTillaart commented 3 years ago

which library is #include mcp_can commented out the CAN bus stuff and this code compiles (after a few fixes)

#include "ADS1X15.h"
// #include <elapsedMillis.h>

// #include <mcp_can.h>
#include <SPI.h>

// elapsedMillis ADSmillis1;

// MCP_CAN CAN0(10);     // Set CS to pin 10

ADS1115 ADS0(0x48);
ADS1115 ADS1(0x49);

uint8_t channel = 0;
int16_t val0[4] = { 0, 0, 0, 0 };
int16_t val1[4] = { 0, 0, 0, 0 };
int     idx = 0;

uint32_t lastTime = 0, now = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

//  // Initialize MCP2515 running at 16MHz with a baudrate of 500kb/s and the masks and filters disabled.
//  if (CAN0.begin(MCP_ANY, CAN_500KBPS, MCP_16MHZ) == CAN_OK) 
//  {
//    Serial.println("MCP2515 CAN0 Initialized Successfully!");
//  }
//  else Serial.println("Error Initializing MCP2515...");
//  CAN0.setMode(MCP_NORMAL);   // Change to normal mode to allow messages to be transmitted

  ADS0.begin();
  ADS0.setGain(0);
  ADS0.setDataRate(4);

  ADS1.begin();
  ADS1.setGain(0);
  ADS1.setDataRate(4);

  ADS_request_all();
}

void loop()
{
  while (ADS_read_all());  // we need to continue sampling.

  // we have all 8 values
  ADS_print_all();
  ADS_send_all();
  delay(1000);      // wait a second.
  ADS_request_all();
}

void ADS_request_all()
{
  ADS0.requestADC(idx);
  ADS1.requestADC(idx);
}

bool ADS_read_all() 
{
  // if both ADS are ready
  if ((ADS0.isBusy() == false) && (ADS1.isBusy() == false))
  {
    val0[idx] = ADS0.getValue() * 0.1875;
    val1[idx] = ADS1.getValue() * 0.1875;
    idx++;
    if (idx < 4)
    {
      ADS0.requestADC(idx);
      ADS1.requestADC(idx);
      return true;
    }
    return false;
  }
  return true; 
}

void ADS_print_all()
{
  // TIMESTAMP
  // Serial.print(millis());
  // Serial.print("\t");
  // PRINT ALL VALUES OF ADC0
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val0[i]);
    Serial.print("\t");
  }
  // PRINT ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val1[i]);
    Serial.print("\t");
  }
  Serial.println();
}

void ADS_send_all()
{
  // SEND ALL VALUES OF ADC0
  byte stmp[8];
  for (int i = 0; i < 4; i++)
  {
    stmp[ i * 2] = val0[i] / 256;
    stmp[ i * 2 + 1] = val0[i] % 256;
    // CAN0.sendMsgBuf(0x70, 0, 8, stmp);
  }
  // SEND ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    stmp[ i * 2] = val1[i] / 256;
    stmp[ i * 2 + 1] = val1[i] % 256;
    // CAN0.sendMsgBuf(0x71, 0, 8, stmp);
  }
}

// -- END OF FILE --
Mplex72 commented 3 years ago

Here it is;

https://github.com/coryjfowler/MCP_CAN_lib

Mplex72 commented 3 years ago

Compiles but does not run, it still seems to get stuck in the isBusy check

RobTillaart commented 3 years ago

you need to reset idx = 0 at some point.

RobTillaart commented 3 years ago

slightly modified version - without CAN bus stuff and some debug print statements.

Can you run it and post the output?

//
//    FILE: ADS_async_8_channel.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo (there are more ways to do this)
//    DATE: 2021-07-05
//     URL: https://github.com/RobTillaart/ADS1X15

#include "ADS1X15.h"

ADS1115 ADS0(0x48);
ADS1115 ADS1(0x49);

int16_t val0[4] = { 0, 0, 0, 0 };
int16_t val1[4] = { 0, 0, 0, 0 };
int     idx = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS0.begin();
  ADS1.begin();
  idx = 0;
  ADS_request_all();
}

void loop()
{
  Serial.println(__FUNCTION__);
  // wait until all is read...
  while (ADS_read_all());

  // we have all 8 values
  ADS_print_all();

  delay(1000);      // wait a second.
  ADS_request_all();
}

void ADS_request_all()
{
  Serial.println(__FUNCTION__);
  ADS0.requestADC(idx);
  ADS1.requestADC(idx);
}

bool ADS_read_all()
{
  if (ADS0.isBusy() || ADS1.isBusy()) return true;
  Serial.print("IDX:\t");
  Serial.println(idx);
  val0[idx] = ADS0.getValue();
  val1[idx] = ADS1.getValue();
  idx++;
  if (idx < 4)
  {
    ADS_request_all();
    return true;
  }
  idx = 0;
  return false;
}

void ADS_print_all()
{
  Serial.println(__FUNCTION__);
  // TIMESTAMP
  // Serial.print(millis());
  // Serial.print("\t");
  // PRINT ALL VALUES OF ADC0
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val0[i]);
    Serial.print("\t");
  }
  // PRINT ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val1[i]);
    Serial.print("\t");
  }
  Serial.println();
}

// -- END OF FILE --
Mplex72 commented 3 years ago

It compiles, It display LOOP as last output on serial monitor;

\Documents\Arduino\ADS1115_8ch_CAN_06__test1\ADS1115_8ch_CAN_06__test1.ino ADS1X15_LIB_VERSION: 0.3.1 ADS_request_all loop

RobTillaart commented 3 years ago

mmmm , please replace setup()

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS0.begin();
  ADS1.begin();
  Serial.println(ADS0.isConnected());
  Serial.println(ADS1.isConnected());

  idx = 0;
  ADS_request_all();
}
Mplex72 commented 3 years ago

output

Documents\Arduino\ADS1115_8ch_CAN_06__test1\ADS1115_8ch_CAN_06__test1.ino ADS1X15_LIB_VERSION: 0.3.1 1 0 ADS_request_all loop

RobTillaart commented 3 years ago

So device ADS1115 ADS1(0x49); is not visible, think you need to check wiring and address lines .

Mplex72 commented 3 years ago

sorry , yes its right , now 1 item on it. In 5 minutes 2 connected

RobTillaart commented 3 years ago

Which country are you from? (just interested where my libs go to, I'm from the Netherlands)

RobTillaart commented 3 years ago

Here it is;

https://github.com/coryjfowler/MCP_CAN_lib

Is not supported in the library manager of the IDE unfortunately .

Mplex72 commented 3 years ago

Not that far away :-) near Zwolle,

Sorry , have to combine 2 new ADC for testing again , previous units not at hand back in half an hour

Mplex72 commented 3 years ago

This is working


//
//    FILE: ADS_async_8_channel.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// PURPOSE: demo (there are more ways to do this)
//    DATE: 2021-07-05
//     URL: https://github.com/RobTillaart/ADS1X15

#include "ADS1X15.h"

ADS1115 ADS0(0x48);
ADS1115 ADS1(0x49);

int16_t val0[4] = { 0, 0, 0, 0 };
int16_t val1[4] = { 0, 0, 0, 0 };
int     idx = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  ADS0.begin();
  ADS1.begin();
  Serial.println(ADS0.isConnected());
  Serial.println(ADS1.isConnected());

  idx = 0;
  ADS_request_all();
}

void loop()
{
  Serial.println(__FUNCTION__);
  // wait until all is read...
  while (ADS_read_all());

  // we have all 8 values
  ADS_print_all();

  delay(1000);      // wait a second.
  ADS_request_all();
}

void ADS_request_all()
{
  Serial.println(__FUNCTION__);
  ADS0.requestADC(idx);
  ADS1.requestADC(idx);
}

bool ADS_read_all()
{
  if (ADS0.isBusy() || ADS1.isBusy()) return true;
  Serial.print("IDX:\t");
  Serial.println(idx);
  val0[idx] = ADS0.getValue();
  val1[idx] = ADS1.getValue();
  idx++;
  if (idx < 4)
  {
    ADS_request_all();
    return true;
  }
  idx = 0;
  return false;
}

void ADS_print_all()
{
  Serial.println(__FUNCTION__);
  // TIMESTAMP
  // Serial.print(millis());
  // Serial.print("\t");
  // PRINT ALL VALUES OF ADC0
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val0[i]);
    Serial.print("\t");
  }
  // PRINT ALL VALUES OF ADC1
  for (int i = 0; i < 4; i++)
  {
    Serial.print(val1[i]);
    Serial.print("\t");
  }
  Serial.println();
}

// -- END OF FILE --`
Mplex72 commented 3 years ago

serial output

s\Documents\Arduino\ADS1115_8ch_CAN_06__test1\ADS1115_8ch_CAN_06__test1.ino ADS1X15_LIB_VERSION: 0.3.1 1 1 ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all IDX: 3 ADS_print_all 1752 1944 3015 3023 2915 2923 2930 2919
ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all IDX: 3 ADS_print_all 1753 1953 3001 3050 2915 2928 2915 2925
ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all

Mplex72 commented 3 years ago

Stop further test , need to debug something first !

RobTillaart commented 3 years ago

Good to see the core is now working.

Please uncomment the 2 lines to add timestamp to the output. That will give a good estimate of the performance.

  // TIMESTAMP
  // Serial.print(millis());
  // Serial.print("\t");
  // PRINT ALL VALUES OF ADC0
Mplex72 commented 3 years ago

App. 46 millis.

s\Documents\Arduino\ADS_async_8_channel.ino\ADS_async_8_channel.ino.ino ADS1X15_LIB_VERSION: 0.3.1 1 1 ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all IDX: 3 ADS_print_all 49 3715 3443 3263 3278 2938 2946 2948 2948
ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all IDX: 3 ADS_print_all 1093 3719 3449 3258 3293 2927 2948 2947 2953
ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all IDX: 3 ADS_print_all 2139 3720 3441 3255 3287 2934 2944 2949 2937

RobTillaart commented 3 years ago

so it works, time to comment the print statements so the output is only sampled values.

Mplex72 commented 3 years ago

95 millis when requested with a delay of 50 millis.

IDX: 3 ADS_print_all 19945 3719 3440 3249 3272 2947 2951 2964 2947
ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all IDX: 3 ADS_print_all 20040 3716 3438 3264 3275 2956 2953 2957 2938
ADS_request_all loop IDX: 0 ADS_request_all IDX: 1 ADS_request_all IDX: 2 ADS_request_all IDX: 3 ADS_print_all 20135 3715 3445 3240 3275 2944 2956 2954 2944
ADS_request_all

AND reguested with 20 millis delay; 42886
42948
43010
43072
43134
43197
43258
43321
43382
43445
43507
43569
43631 // all in millis per round of 8 values

RobTillaart commented 3 years ago

so about 62 - 63 millis for eight 16 bit values is not that bad...

Mplex72 commented 3 years ago

Nope , not bad at all. yet to figure out how i can do the can messages without disturbing the speed.

When you eventually have to test 4 units ? Now have 4 units working ready for test .

RobTillaart commented 3 years ago

I already placed them in my basket - https://www.tinytronics.nl/shop/nl/sensoren/stroom-spanning - so they will be included in my next order there. They also have cheaper and faster B-stock (it says 1115 but they are 1015's - ideal to do testing. Maybe I should just order a bunch of those too.

Mplex72 commented 3 years ago

Hey , thats not bad for testing , should do much higher speed too. maybe I can combine the 12bit for the highspeed channels.

I used the AD7606 too for high speed , nice unit but is SPI and did not combine good with 8 channel max31855 use 1 of my units for testing ? :-)

RobTillaart commented 3 years ago

try higher I2C speed

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("ADS1X15_LIB_VERSION: ");
  Serial.println(ADS1X15_LIB_VERSION);

  Wire.setClock(400000);  // might try 600000 too

  ADS0.begin();
  ADS1.begin();
  Serial.println(ADS0.isConnected());
  Serial.println(ADS1.isConnected());

  idx = 0;
  ADS_request_all();
}
Mplex72 commented 3 years ago

checked , verify connected gives back 0 (zero) for each ADC when not connected.

s\Documents\Arduino\ADS1115_8ch_CAN_06__test5\ADS1115_8ch_CAN_06__test5.ino ADS1X15_LIB_VERSION: 0.3.1 0 0 ADS_request_all loop

Mplex72 commented 3 years ago

I2C frequency to 400khz still gives 43millis that is the same as with 100khz , both requested with 1000 millis delay tested with 16channels gives the same millis , ADC datarate is important (rate5 is optimum) and react to 37 millis

RobTillaart commented 3 years ago

So I2C communication is just a small part of the time used. How much channels do you need to monitor?

Mplex72 commented 3 years ago

16 channels. tested the isbusy check now on 2 adc units , millis go from 44 to 11 millis. very costly....

RobTillaart commented 3 years ago

So that is faster if i understand correctly, What do you mean by "very costly"?

Mplex72 commented 3 years ago

well , timewise a factor 4 ! from 44 to 11 millis processing time. without check it is much faster. 16 channels without check is 22 millis

RobTillaart commented 3 years ago

I still not understand. What do you mean with the "without check" ?

Can you post the code snippet that changed by removing the check you mean?

Mplex72 commented 3 years ago

There is a possibility that it read old data values ?



bool ADS_read_all()
{
 // if (ADS0.isBusy() || ADS1.isBusy()) return true;
  Serial.print("IDX:\t");
  Serial.println(idx);
  val0[idx] = ADS0.getValue();
  val1[idx] = ADS1.getValue();
  idx++;
  if (idx < 4)
  {
    ADS_request_all();
    return true;
  }
  idx = 0;
  return false;
}
RobTillaart commented 3 years ago

// if (ADS0.isBusy() || ADS1.isBusy()) return true;

that line takes care you wait for the new measurement to be ready. you should notice that in the data that if you skip that test you get more often same value

Mplex72 commented 3 years ago

That should mean I get the adc sample rate at max ~26Hz for 4 , 8 , and 22hz for 16 channels . with 4 or 16 channels doesn,t make much difference. And I can get 26Hz only on datarate(5) , higher modes do not give extra speed wich surprised me. I hoped to do100hz sampling .

RobTillaart commented 3 years ago

Max number of samples of the ADS1115 is according to the datasheet 860 samples per second. The ADS1015 (12 bit) goes up to 3300.

Did you study the datasheet about how to get the max data rate?

Recall you started this thread with a question about asynchronous calls and maybe that is not the right way?

I do not know what process you want to monitor and what your minimal requirements are, Maybe time to explain the background (because this issue is not about a problem in the library)

Mplex72 commented 3 years ago

I read the datasheet (maybe did understand it wrong) the impression that I had was that I could more efficient readout my data because I shouldn,t have to wait for conversion ready. ie.

-bad point , cost you a lot of time.

Mplex72 commented 3 years ago

The use case ;

To sample 16 channels Voltage data for a CAN datalogging system I need the 16 values sampled and send at 100 Hz. preferably without a lot of noise in the signal >

I had the idea to sample (low) datarate@475 SpS for lowest possible noise that should be enough for 100SpS for 4 values

then with assych read collect data from 4 ADC units without having the read delays
and keep the sample rate the same 100 hz