Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem adding multiple sensors #5

Open
ziatajo opened this issue Nov 29, 2018 · 50 comments · Fixed by brendanmatkin/ADS126X#1 · May be fixed by #21
Open

Problem adding multiple sensors #5

ziatajo opened this issue Nov 29, 2018 · 50 comments · Fixed by brendanmatkin/ADS126X#1 · May be fixed by #21

Comments

@ziatajo
Copy link

ziatajo commented Nov 29, 2018

Hi,
Maybe I'm just too stupid, but I cannot even manage to add a second sensor.

I used the example and successfully connected a full-bridge loadcell to AIN0-AIN1.
Than I wanted to add a second full-bridge loadcell to AIN2-AIN3.
I just copied the code: Defined additional POS-NEG pins, and read the value:
voltage1 = adc1.readADC1(pos_pin1,neg_pin1); // read the voltage
voltage2 = adc1.readADC1(pos_pin2,neg_pin2); // read the voltage

However my data for both sensors is now just showing 0 or -1.

What am I doing wrong?

Thank you and best regards

@Molorius
Copy link
Owner

No need to self-deprecate! Let me make sure I understand your problem.
You were able to successfully use the example code. Then you changed the loop function to something like:

void loop() {
  long voltage1 = adc.readADC1(pos_pin1,neg_pin1);
  long voltage2 = adc.readADC2(pos_pin2,neg_pin2);
  Serial.print(voltage1);
  Serial.print(", ");
  Serial.println(voltage2); // send voltage through serial
  delay(1000); // wait 1 second
}

and now you are only getting 0 and -1. Is that correct?

@ziatajo
Copy link
Author

ziatajo commented Nov 29, 2018

Exactly, both sensor values are only 0 or -1 now.
I'm using an Adafruit Feather ESP32 if that helps. Let me know if you need something else.
Thank you for your help.

@Molorius
Copy link
Owner

Are you using 3.3V on DVDD and 5V on AVDD? The esp32 is not 5V tolerant, so the ads126x digital side needs to be run at 3.3V (or use level shifters). The ads126x analog side requires 5V to operate.

Try commenting out one of the voltage read lines, maybe there was an introduced change that messed with the reading.

I do not have an ads126x readily available, but I had problems with it when uploading new code to a microcontroller. Try uploading the code, disconnecting all power to your circuit for a few seconds, then power it back on.

@ziatajo
Copy link
Author

ziatajo commented Nov 30, 2018

That is a good point. I have a Step-Up for the 5V, but connected DVDD and AVDD to 5V now I changed that DVDD is on the 3.3V. Unfortunately it didn't change the result and it's still the same.
My code at the moment is:

#include <ADS126X.h>

ADS126X adc1; // start the class

int chip_select1 = 4; // Arduino pin connected to CS on ADS126X

long voltage1 = 0;
long voltage2 = 0;

int pos_pin1 = 0; // ADS126X pin AIN0, for positive input
int neg_pin1 = 1; // ADS126X pin AIN1, for negative input

int pos_pin2 = 2; 
int neg_pin2 = 3; 


void setup() {
 Serial.begin(115200);
 adc1.begin(chip_select1); // setup with chip select pin0.
 adc1.startADC1(); // start conversion on ADC1
 Serial.println("Reading Voltages:");
}

void loop() {

 voltage1 = adc1.readADC1(pos_pin1,neg_pin1); // read the voltage
 Serial.print(voltage1); // send voltage through serial
 delay(100);
 Serial.print(" , ");
 voltage2 = adc1.readADC1(pos_pin2,neg_pin2); // read the voltage
 Serial.println(voltage2); // send voltage through serial
 delay(100);
} 

I only get 0 and -1 (don't know when it is changing between the two).
When I comment out one of the "voltagex=adc1.readADC1...." lines the still active sensor works. (it works for both sensors)
I also changed the delays but longer or shorter didn't help too.

EDIT: I just tried it with a Teensy 3.2 instead of the ESP32. I get the same "error". One sensor works, two sensors don't.

@Molorius
Copy link
Owner

I think I know what the problem is. As a quick test, could you try reading each voltage twice? So:

void loop() {
 adc1.readADC1(pos_pin1,neg_pin1);
 voltage1 = adc1.readADC1(pos_pin1,neg_pin1); // read the voltage
 Serial.print(voltage1); // send voltage through serial
 delay(100);
 Serial.print(" , ");
 adc1.readADC1(pos_pin2,neg_pin2);
 voltage2 = adc1.readADC1(pos_pin2,neg_pin2); // read the voltage
 Serial.println(voltage2); // send voltage through serial
 delay(100);
} 

@SammyRamone
Copy link

We have exactly the same issue. We also tried you code from last comment and also only recieved "0,0". A fix would be great.
Reading just one of the sensors works perfectly well.
Btw, thanks for the library :)

@ziatajo
Copy link
Author

ziatajo commented Dec 3, 2018

I let the ADS1262 in my office over the weekend, thats why I could test it not before now.
As SammyRamone state, also with the double reading it doesn't work. However there is a small difference.
With reading each voltage twice, I always only get "0 , 0", as soon as I read it only once it will change between 0 or -1 (no pattern).

@q-bird
Copy link

q-bird commented Dec 3, 2018

Do you get the same problem with both of ContinuousMode and PulseMode?

@ziatajo
Copy link
Author

ziatajo commented Dec 3, 2018

How do I change that? :)

@q-bird
Copy link

q-bird commented Dec 3, 2018

You can go to README.md and find setContinuousMode() or setPulseMode()

@q-bird
Copy link

q-bird commented Dec 3, 2018

And pls also try to use this func void setDelay(uint8_t del) to see if it can solve something!

@ziatajo
Copy link
Author

ziatajo commented Dec 3, 2018

I changed it like the following. In two steps, first only the PulseMode(), than with delay. Both doesn't change anything. adc1.setContinuousMode(); + delay doesn't help too.

void setup() {
  Serial.begin(115200);
  adc1.begin(chip_select1); // setup with chip select pin0.
  adc1.setDelay(ADS126X_DELAY_8_8);
  adc1.setPulseMode();
  adc1.startADC1(); // start conversion on ADC1
  Serial.println("Reading Voltages:");
}

@q-bird
Copy link

q-bird commented Dec 3, 2018

With the PulseMode, then can you try something like this?

void loop() {
 adc1.startADC1();
 voltage1 = adc1.readADC1(pos_pin1,neg_pin1); // read the voltage
 Serial.print(voltage1); // send voltage through serial
 adc1.stopADC1();

 delay(1000);
 Serial.print(" , ");

 adc1.startADC1();
 voltage2 = adc1.readADC1(pos_pin2,neg_pin2); // read the voltage
 Serial.println(voltage2); // send voltage through serial
 adc1.stopADC1();

 delay(1000);
} 

(The purpose is just to figure out the problem we are encountering by using some different ways to read)

@ziatajo
Copy link
Author

ziatajo commented Dec 3, 2018

With this I get the same output as at the start:

Reading Voltages:
0 , -1
0 , 0
0 , -1
-1 , -1
-1 , 0
-1 , 0
-1 , 0
-1 , -1
0 , -1
-1 , 0
0 , -1
-1 , 0
-1 , 0
0 , -1
-1 , 0
-1 , -1

@ziatajo
Copy link
Author

ziatajo commented Dec 8, 2018

Hi,
Do you have any other ideas, how I could solve this?

Thank you.

@q-bird
Copy link

q-bird commented Dec 9, 2018

Hi @ziatajo

I think we should try with single-ended mode to see :)
Instead of wiring your sensor1 to pos_pin1 and neg_pin1 , now you just connect the positive side of sensor1 to pos_pin1, and the negative side you connect to GND of the board.
Do the same thing with your sensor2.
Then in the code, you change to something like this:

adc1.readADC1(pos_pin1, ADS126X_DIGITAL); 
...
adc1.readADC1(pos_pin2, ADS126X_DIGITAL);

(I think that you should test single-ended mode with one sensor first, then test with two sensors later to see if the single-ended working well or not)

@ziatajo
Copy link
Author

ziatajo commented Dec 10, 2018

Hi @q-bird

I changed my code to your suggestion. If I read just one sensor it works, if I try to read two I get the same result as before (0 or -1)

@q-bird
Copy link

q-bird commented Dec 10, 2018

Currently, the delay between two sensors is 1s. What will happen if you change to 10s or 20s (jst for testing)?
--> delay(10000); (change both lines)

@ziatajo
Copy link
Author

ziatajo commented Dec 10, 2018

void loop() {
 voltage1 = adc1.readADC1(pos_pin1,ADS126X_DIGITAL); // read the voltage
 Serial.print(voltage1); // send voltage through seria
 delay(10000);
 Serial.print(" , ");
 voltage2 = adc1.readADC1(pos_pin2,ADS126X_DIGITAL); // read the voltage
 Serial.println(voltage2); // send voltage through serial
 delay(10000);
} 

This code, still the same.

@q-bird
Copy link

q-bird commented Dec 10, 2018

OK, so please try this one

...
#define N 10
...

void loop() {
 for(int i = 0; i < N; i++) {
   voltage1 = adc1.readADC1(pos_pin1,ADS126X_DIGITAL); // read the voltage
   delay(100);
 }
 Serial.print(voltage1); // send voltage through seria
 delay(10000);

 Serial.print(" , ");
 for(int i = 0; i < N; i++) {
   voltage2 = adc1.readADC1(pos_pin2,ADS126X_DIGITAL); // read the voltage
   delay(100);
 }
 Serial.println(voltage2); // send voltage through serial
 delay(10000);
} 

@ziatajo
Copy link
Author

ziatajo commented Dec 10, 2018

Ok, it looks better :)
The values are positive when i press my FSR resistive sensor.

Reading Voltages:
-255463651 , -255539036
-255456798 , -255571295
2130455999 , -255822856
-253952042 , -252904811
-253789455 , 2118578383
357117345 , -242835174
-242840129 , -243950477
-247262989 , -246449838
-247997117 , -246418198

@ziatajo
Copy link
Author

ziatajo commented Dec 10, 2018

Ok, so I did some more tests. It seems that the double read would work, but we had to little delay. (sorry for that failed test before)
It works now for N>=2 and d >= 52.
This is the current code:

#include <ADS126X.h>

ADS126X adc1; // start the class
#define N 2
#define d 52

int chip_select1 = 10; // Arduino pin connected to CS on ADS126X

long voltage1 = 0;
long voltage2 = 0;

int pos_pin1 = 0; // ADS126X pin AIN0, for positive inpu
int pos_pin2 = 1; 

void setup() {
  Serial.begin(115200);
  adc1.begin(chip_select1); // setup with chip select pin0.
  adc1.startADC1(); // start conversion on ADC1
  Serial.println("Reading Voltages:");
}
void loop() {
 for(int i = 0; i < N; i++) {
   voltage1 = adc1.readADC1(pos_pin1,ADS126X_DIGITAL); // read the voltage
   delay(d);
 }
 Serial.print(voltage1); // send voltage through serial

 Serial.print(" , ");
 for(int i = 0; i < N; i++) {
   voltage2 = adc1.readADC1(pos_pin2,ADS126X_DIGITAL); // read the voltage
   delay(d);
 }
 Serial.println(voltage2); // send voltage through serial
} 

EDIT:

I tried it know also with:

adc1.begin(chip_select1); // setup with chip select pin0.
  adc1.setRate(ADS126X_RATE_38400);
  adc1.startADC1(); // start conversion on ADC1

now I can reduce the delay to 170 Microseconds.
Later I would need reading 4 differential sensors with at least 1kHz. Would that be possible somehow?

@q-bird
Copy link

q-bird commented Dec 11, 2018

Good to hear!
Now I think you can change back to read from pos_pins and neg_pins.
f = 1kHz -> T = 1ms = 1000us
And in order to know how long your reading will take, we will try to do something like:

...
unsigned long us = 0;
...
void loop() {
  us = micros(); // micro seconds

  /* Reading code */
  // Your reading code here
  /* End of reading code */
  
  // Printing the time of reading code
  Serial.print("T = "); 
  Serial.print(micros() - us); 
  Serial.println("us");
}

If you see the value printed is less than 1000us meaning it matches with your requirement! if not, let's try to change N and d and the setRate to have the best results

@Molorius
Copy link
Owner

Thanks for finding the problem, hopefully I will have time to push a fix this week.

The problem is it needs to restart a conversion when changing pins, so you need to do one dummy read to change the pin, delay for at least one conversion cycle, then save the next read. The necessary delay is dependent on the sampling rate (the setRate() function). It defaults to 20 SPS, so a delay of at least 50 milliseconds (I would do 51 to be on the safe side). You can also check for when the DRDY pin is pulled low if you need precise timing.

@ziatajo
Copy link
Author

ziatajo commented Dec 14, 2018

@q-bird yes I took some more measurements, with reading every sensor twice (as it has to be now) and some Serialprinting I can reach something about 970us. So if @Molorius can solve the problem of necessary double readings, I can probably read 4 sensors within 1kHZ.

But I don't totally understand it. The samling rate of 38400 would mean 1 reading every 26 us. Is the read command taking that much longer, so that 170us is the minimum I can get?

Also, do you know what how I can do differential reading to the 2.5V internal reference?
Would that be one of these?:
ADS126X_TEMP | Temperature sensor monitor positive/negative
ADS126X_ANALOG | Analog power supply monitor positive/negative
ADS126X_DIGITAL | Digital power supply monitor positive/negative
ADS126X_TDAC | TDAC test signal positive/negative
ADS126X_FLOAT | Float (open connection)

If I need to measure 6 sensors, would it be possible to differential read all to the same "Neg-PIN"?

@SammyRamone
Copy link

Any updates to this? Would be nice to have a real fix without the double readings

@ziatajo
Copy link
Author

ziatajo commented Jan 29, 2019

An update would really be great, I just made some further tests.
I'm using now 5 full bridge load cells. So I'm always reading between Pos and Neg Pins. I now had to increase N to 4 compared to 2 before. I cannot explain why, but it makes the hole process alot slower.
I also printed the 4 read values of one Sensor, and the first three are zero or -1 and the 4th has the corret value.
Thank you very much.

#include <ADS126X.h>

ADS126X adc1; // start the class
#define N 4
int d=30;

int chip_select1 = 4; // Arduino pin connected to CS on ADS126X

long voltage1 = 0;
long voltage2 = 0;
long voltage3 = 0;
long voltage4 = 0;
long voltage5 = 0;

int pos_pin1 = 0; // ADS126X pin AIN0, for positive inpu
int neg_pin1 = 1;

int pos_pin2 = 2; 
int neg_pin2 = 3; 

int pos_pin3 = 4; 
int neg_pin3 = 5; 

int pos_pin4 = 6; 
int neg_pin4 = 7; 

int pos_pin5 = 8; 
int neg_pin5 = 9; 

int neg_pinInt = ADS126X_REF_POS_INT;
unsigned long us = 0;
unsigned long diff = 0;

void setup() {
  Serial.begin(2000000);
  adc1.begin(chip_select1); // setup with chip select pin0.
  adc1.setRate(ADS126X_RATE_38400);
  adc1.setGain(ADS126X_GAIN_32);
  adc1.startADC1(); // start conversion on ADC1
  Serial.println("Reading Voltages:");
}
void loop() {
 // us = micros();

 for(int i = 0; i < N; i++) {
   voltage1 = adc1.readADC1(pos_pin1,neg_pin1); // read the voltage
   voltage1 =voltage1>>16;
   delayMicroseconds(d); 
 }
 Serial.print(voltage1); // send voltage through serial
 Serial.print(",");


 for(int i = 0; i < N; i++) {
   voltage2 = adc1.readADC1(pos_pin2,neg_pin2); // read the voltage
   voltage2 =voltage2>>16;
   delayMicroseconds(d);
 }
 Serial.print(voltage2); // send voltage through serial.
 Serial.print(",");

 for(int i = 0; i < N; i++) {
   voltage3 = adc1.readADC1(pos_pin3,neg_pin3); // read the voltage
   voltage3 =voltage3>>16;
   delayMicroseconds(d); 
 }
 Serial.print(voltage3); // send voltage through serial
 Serial.print(",");
 
 for(int i = 0; i < N; i++) {
   voltage4 = adc1.readADC1(pos_pin4,neg_pin4); // read the voltage
    voltage4 =voltage4>>16;
   delayMicroseconds(d); 
 }
 Serial.print(voltage4); // send voltage through serial
 Serial.print(",");

 for(int i = 0; i < N; i++) {
   voltage5 = adc1.readADC1(pos_pin5,neg_pin5); // read the voltage
    voltage5 =voltage5>>16;
   delayMicroseconds(d); 
 }
 Serial.println(voltage5); // send voltage through serial
// Serial.print(",");
// diff=micros() - us;
// Serial.println(diff);
   
} 

@SammyRamone
Copy link

Sorry for being annoying, but it would still be great to have a fix for this :)

@Molorius
Copy link
Owner

It's not annoying, they're helpful reminders. I keep trying to find my ADS1262, but I can't seem to find it for testing. I will set up a branch for this so someone else can test before I put it in the main. I'll post here when I have tests to be done, but I am pretty busy at the moment so it may take a while. In the meantime, just use the DRDY pin to verify when the conversion is complete.

@ziatajo
Copy link
Author

ziatajo commented Mar 4, 2020

Hi, it's me again.

I'm still using the ADS1262. The last project I could ignore the "lower" measurement frequency. Now we have a new project where we would like to get the data of 8 sensors with ~1kHz.
Therefore it would be great if this problem can be solved.
I'm not a pro in programming,... But I invested quite some time now to investigate this problem. I try to describe my findings and hope you can use them to upgrade the library.

  1. You start the
    int32_t ADS126X::readADC1(uint8_t pos_pin,uint8_t neg_pin)
    with
    if(cs_used) _ads126x_write_pin_low(cs_pin);
    However, as soon as the pos/neg - pins are changed, you call ADS126X::writeRegister(ADS126X_INPMUX);
    this function calls
    void ADS126X::writeRegisters(uint8_t start_reg,uint8_t num)
    which also set the CS_Pin low at the start and low at the end.
    There fore the CS_Pin is already HIGH when doing the rest of the readADC1 function. To try that out, just moved the
    if((REGISTER.INPMUX.bit.MUXN != neg_pin) || (REGISTER.INPMUX.bit.MUXP != pos_pin)) { REGISTER.INPMUX.bit.MUXN = neg_pin; REGISTER.INPMUX.bit.MUXP = pos_pin; ADS126X::writeRegister(ADS126X_INPMUX); // replace on ads126x }
    at the start of the function just before
    if(cs_used) _ads126x_write_pin_low(cs_pin);

  2. Until now it worked by waiting some time after each readADC1 and reading the same pins multiple times.
    To test this, I added
    #include <Arduino.h>
    and a Microsecond delay after writing the registers:

if((REGISTER.INPMUX.bit.MUXN != neg_pin) || (REGISTER.INPMUX.bit.MUXP != pos_pin)) {
    REGISTER.INPMUX.bit.MUXN = neg_pin;
    REGISTER.INPMUX.bit.MUXP = pos_pin;
	ADS126X::writeRegister(ADS126X_INPMUX);// replace on ads126x
	delayMicroseconds(200);
	}

The higher I make this delay, the less measurements with readADC1 I have to make. The minimal delay to only read twice depends on the samplingRate (here 38400) and probably the SPI Rate (here 80000000).

  1. In the datasheet of the ADS1262 p.88 it's written:

Writing new data to certain registers results in restart of conversions that are in progress.The registers that result in conversion restart(either ADC1or ADC2)are shown in the ADC Restart column in Table38. The device drives the DRDY output high when ADC1 restarts. Additionally, data can be written as a block to multiple registers using a single command. If data are written as a block,the data of certain registers take effect immediately as the data are shifted in, while the data of other registers are buffered and take effect when the command is fully completed.The registers that update as a group are identified in the Group Update column in Table 38. The group update registers that pertain to ADC1 operation are labeled Group1. The group update registers that pertain to ADC2 operation are labeled Group2. Update registers as a groupt o minimize the ADC recovery time after a configuration change.If the write command is terminated before completion,the data of group registers are not saved.

Could it be a problem that you only write the INPMUX register and not all registers of Group1?
I tried to implement that into the library, but couldn't get a good result.

void ADS126X::writeRegisters(uint8_t start_reg, uint8_t num) { // page 87
	if (cs_used) _ads126x_write_pin_low(cs_pin);
	if (start_reg == ADS126X_INPMUX) {
		uint8_t buff[50] = { 0 }; // plenty of room, all zeros

		buff[0] = ADS126X_MODE0 | ADS126X_WREG; // first byte is starting register with write command
		buff[1] = 7 - 1; // tell how many registers to write, see datasheet

		buff[2] = REGISTER_ARRAY[ADS126X_MODE0];
		buff[3] = REGISTER_ARRAY[ADS126X_MODE1];
		buff[4] = REGISTER_ARRAY[ADS126X_MODE2];
		buff[5] = REGISTER_ARRAY[ADS126X_INPMUX];
		buff[6] = REGISTER_ARRAY[ADS126X_IDACMUX];
		buff[7] = REGISTER_ARRAY[ADS126X_IDACMAG];
		buff[8] = REGISTER_ARRAY[ADS126X_REFMUX];// put the desired register values in buffer
		/*for (uint8_t i = 0; i < num; i++) {
			buff[i + 2] = REGISTER_ARRAY[i + start_reg];
		}*/

		// have the microcontroller send the amounts, plus the commands
		_ads126x_spi_rw(buff, 7 + 2);
	}
	else{
	uint8_t buff[50] = { 0 }; // plenty of room, all zeros

	buff[0] = start_reg | ADS126X_WREG; // first byte is starting register with write command
	buff[1] = num - 1; // tell how many registers to write, see datasheet

	// put the desired register values in buffer
	for (uint8_t i = 0; i < num; i++) {
		buff[i + 2] = REGISTER_ARRAY[i + start_reg];
	}

	// have the microcontroller send the amounts, plus the commands
	_ads126x_spi_rw(buff, num + 2);
	}
  if(cs_used) _ads126x_write_pin_high(cs_pin);
}

Does this help? Do you have any ideas? I can test things if you need to! If necessary I could also send you an ADS1262..

Thank you.

@nravirke
Copy link

nravirke commented Jun 7, 2020

Hi,
Any solution for using more than 1 Channel or sensor on ads1262.
Thanks in advance.
Ravi

@nravirke
Copy link

nravirke commented Jun 9, 2020

Hi Friends,
Finally I think Got the Solution.
I am Testing it...

@SammyRamone
Copy link

Hi Friends,
Finally I think Got the Solution.
I am Testing it...

We would also still be interested in a solution, so please tell us when you found something :)

@nravirke
Copy link

Hi,
Pl Try This Program..

// DATE: 09 06 2020 AT 20:23
// R K ENTERPRISES
// RAVI N
//[email protected]
/*Wiring to your Arduino
32BITRKE.ino
ads1262_Reg_Write(INPMUX, 0x01); // SELECTING CH0 & CH1
ads1262_Reg_Write(INPMUX, 0x23); // SELECTING CH2 & CH3
ads1262_Reg_Write(INPMUX, 0x45); // SELECTING CH4 & CH5
ads1262_Reg_Write(INPMUX, 0x67); // SELECTING CH6 & CH7
ads1262_Reg_Write(INPMUX, 0x89); // SELECTING CH8 & CH9

this example gives differential voltage across the CHx And CHy in mV
Hooking-up with the Arduino

ads1262 pin label Pin Function Arduino Connection
DRDY Data ready Output pin D6
MISO Slave Out D12
MOSI Slave In D11
SCLK Serial Clock D13
CS Chip Select D7
START Start Conversion D5
PWDN Power Down/Reset D4
DVDD Digital VDD +5V
DGND Digital Gnd Gnd
AN0-AN9 Analog Input Analog Input
AINCOM Analog input common
AVDD Analog VDD -
AGND Analog Gnd -

*/
#include <SPI.h>
#include <math.h>

#define PGA 1 // Programmable Gain = 1
#define VREF 2.5 // 2.494v Internal reference of 2.048V
#define VFSR VREF/PGA //2.50/1 = 2.50
#define FSR (((long int)1<<23)-1)

int CONFIG_SPI_MASTER_DUMMY = 0xFF;
#define RREG 0x20
#define WREG 0x40
#define START 0x08
#define STOP 0x0A
#define RDATA 0x12

//Pins used for the connection with the sensor, the other you need are controlled by the SPI library):
const int ADS1262_DRDY_PIN = 6;
const int ADS1262_CS_PIN = 7;
const int ADS1262_START_PIN = 5;
const int ADS1262_PWDN_PIN = 4;
//Register address
#define POWER 0x01
#define INTERFACE 0x02
#define MODE0 0x03
#define MODE1 0x04
#define MODE2 0x05
#define INPMUX 0x06
#define OFCAL0 0x07
#define OFCAL1 0x08
#define OFCAL2 0x09
#define FSCAL0 0x0A
#define FSCAL1 0x0B
#define FSCAL2 0x0C
#define IDACMUX 0x0D
#define IDACMAG 0x0E
#define REFMUX 0x0F
#define TDACP 0x10
#define TDACN 0x11
#define GPIOCON 0x12
#define GPIODIR 0x13
#define GPIODAT 0x14
#define ADC2CFG 0x15
#define ADC2MUX 0x16
#define ADC2OFC0 0x17
#define ADC2OFC1 0x18
#define ADC2FSC0 0x19
#define ADC2FSC1 0x1A

float volt_V=0;
float volt_mV=0;
volatile int i, data;
volatile char SPI_RX_Buff[10];
volatile long ads1262_rx_Data[10];
volatile static int SPI_RX_Buff_Count = 0;
volatile char *SPI_RX_Buff_Ptr;
volatile int Responsebyte = false;
volatile signed long sads1262Count = 0;
volatile signed long uads1262Count=0;
double resolution;

void setup()
{
// initalize the data ready and chip select pins:
pinMode(ADS1262_DRDY_PIN, INPUT); //Data ready input line
pinMode(ADS1262_CS_PIN, OUTPUT); //Chip enable output line
pinMode(ADS1262_START_PIN, OUTPUT); //Start
pinMode(ADS1262_PWDN_PIN, OUTPUT); //Power down output

digitalWrite(ADS1262_START_PIN, LOW); //Manter o pino LOW e controlar comunicação via código SPI
digitalWrite(ADS1262_CS_PIN, LOW); //Manter o pino LOW para manter comunicação sempre possível

Serial.begin(115200); //inicia comunicação serial
SPI.begin(); // start the SPI library:
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE1));
ads1262_Init(); // initialise ads1262 slave

}

void loop()
{

    // FOR SINGLE ENDED OPERATION CONNECT PIN NUM 3 ( AINCOM ) TO GND

ads1262_Reg_Write(INPMUX, 0x0A);
delay(10);
RKEADC();
Serial.print(" ");
ads1262_Reg_Write(INPMUX, 0x1A);
delay(10);
RKEADC();
Serial.print(" ");
ads1262_Reg_Write(INPMUX, 0x2A);
delay(10);
RKEADC();
Serial.print(" ");
ads1262_Reg_Write(INPMUX, 0x3A);
delay(10);
RKEADC();
Serial.print(" ");
ads1262_Reg_Write(INPMUX, 0x4A);
delay(10);
RKEADC();
Serial.print(" ");
ads1262_Reg_Write(INPMUX, 0x5A);
delay(10);
RKEADC();
Serial.print(" ");
ads1262_Reg_Write(INPMUX, 0x6A);
delay(10);
RKEADC();
Serial.print(" ");
ads1262_Reg_Write(INPMUX, 0x7A);
delay(10);
RKEADC();
delay(3000);
Serial.println(" ");

}

//**************

void RKEADC()
{

while (digitalRead(ADS1262_DRDY_PIN) == HIGH){
}

SPI_RX_Buff_Ptr = ads1262_Read_Data(); //6Bytes <STATUS|DATA1|DATA2|DATA3|DATA4|CHECKSUM>

for(i = 0; i <5; i++) //Remove STATUS byte?
{
SPI_RX_Buff[SPI_RX_Buff_Count++] = *(SPI_RX_Buff_Ptr + i);
}

if(SPI_RX_Buff_Count >= 5) {
ads1262_rx_Data[0]= (unsigned char)SPI_RX_Buff[1]; // read 4 bytes adc count
ads1262_rx_Data[1]= (unsigned char)SPI_RX_Buff[2];
ads1262_rx_Data[2]= (unsigned char)SPI_RX_Buff[3];
ads1262_rx_Data[3]= (unsigned char)SPI_RX_Buff[4];
uads1262Count = (signed long) (((unsigned long)ads1262_rx_Data[0]<<24)|((unsigned long)ads1262_rx_Data[1]<<16)|(ads1262_rx_Data[2]<<8)|ads1262_rx_Data[3]);//get the raw 32-bit adc count out by shifting

sads1262Count = (signed long) (uads1262Count);      // get signed value    
resolution = (double)((double)VREF/pow(2,31));       //resolution= Vref/(2^n-1) , Vref=2.5, n=no of bits
volt_V      = (resolution)*(float)(sads1262Count);     // voltage = resolution * adc count
volt_mV   =   volt_V*1000;                           // voltage in mV
//Serial.print(volt_mV);
//Serial.print(" , ");
//Serial.print(" Volt ");
Serial.print(volt_V,4);
Serial.print("  ");

//Serial.println(" mV");
//delay(10000);
}
SPI_RX_Buff_Count = 0;

}

//*****************

//float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
//{
// return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
//}

void ads1262_Init()
{
ads1262_Reset(); delay(100);
ads1262_Reg_Write(POWER, 0x11);delay(10); //11h (default) internal ref enabled
ads1262_Reg_Write(INTERFACE, 0x05);delay(10); //0D RAVI//05h (default) Status byte enabled, Checksum enablade
ads1262_Reg_Write(MODE0, 0x00);delay(10); //00h (default) Continuous Conv Mode | 0x40 Pulse conversion mode (one shot conversion)
ads1262_Reg_Write(MODE1, 0x00);delay(10); //80h (default) FIR Filter | 00h sinc1 | 60h sinc4
ads1262_Reg_Write(MODE2, 0x06);delay(10); // 5DRAVI //04h (default) PGA enabled 1V/V 20sps| 5Ch 32V/V 7200sps | 5Fh 32V/V 38400sps
//ads1262_Reg_Write(INPMUX, 0x01);delay(10); //01h (default) Multiplexer, AIN0 e AIN1 | 23h AIN2 e AIN3
ads1262_Reg_Write(OFCAL0, 0x00);delay(10); //00h (default) Offset Calibration Registers
ads1262_Reg_Write(OFCAL1, 0x00);delay(10); //00h (default) Offset Calibration Registers
ads1262_Reg_Write(OFCAL2, 0x00);delay(10); //00h (default) Offset Calibration Registers
ads1262_Reg_Write(FSCAL0, 0x00);delay(10); //00h (default) Full-Scale Calibration Registers
ads1262_Reg_Write(FSCAL1, 0x00);delay(10); //00h (default) Full-Scale Calibration Registers
ads1262_Reg_Write(FSCAL2, 0x40);delay(10); //40h (default) Full-Scale Calibration Registers
ads1262_Reg_Write(IDACMUX, 0xBB);delay(10); //BBh (default) Output Multiplexer, no connection, no connection
ads1262_Reg_Write(IDACMAG, 0x00);delay(10); //00h (default) Current magnitude, off
ads1262_Reg_Write(REFMUX, 0x00);delay(10); //00h (default) Reference Multiplexer, 2.5V, 2.5V
ads1262_Reg_Write(TDACP, 0x00);delay(10);//00h (default) TDACP, no connection
ads1262_Reg_Write(TDACN, 0x00);delay(10); //00h (default) TDACN, no connection
ads1262_Reg_Write(GPIOCON, 0x00);delay(10); //00h (default) GPIO not connected
ads1262_Reg_Write(GPIODIR, 0x00);delay(10); //00h (default) GPIO output
ads1262_Reg_Write(GPIODAT, 0x00);delay(10); //00h (default) GPIO low
ads1262_Reg_Write(ADC2CFG, 0x00);delay(10); //00h (default) ADC2
ads1262_Reg_Write(ADC2MUX, 0x01);delay(10); //01h (default)
ads1262_Reg_Write(ADC2OFC0, 0x00);delay(10); //00h (default)
ads1262_Reg_Write(ADC2OFC1, 0x00);delay(10); //00h (default)
ads1262_Reg_Write(ADC2FSC0, 0x00);delay(10); //00h (default)
ads1262_Reg_Write(ADC2FSC1, 0x40);delay(10); //40h (default)
SPI.transfer(START); //Inicia a conversão via código 08h
}

char* ads1262_Read_Data()
{
SPI.transfer(RDATA);
static char SPI_Dummy_Buff[6];
for (int i = 0; i < 6; ++i)
{
SPI_Dummy_Buff[i] = SPI.transfer(CONFIG_SPI_MASTER_DUMMY); //CONFIG_SPI_MASTER_DUMMY - FFh
}
return SPI_Dummy_Buff; // 6Bytes <STATUS|DATA1|DATA2|DATA3|DATA4|CHECKSUM>
}

void ads1262_Reset() //PWDN_PIN MUST BE HIGH FOR OPERATION
{
digitalWrite(ADS1262_PWDN_PIN, HIGH); delay(100);
digitalWrite(ADS1262_PWDN_PIN, LOW); delay(100);
digitalWrite(ADS1262_PWDN_PIN, HIGH); delay(100);
}

void ads1262_Reg_Write (unsigned char READ_WRITE_ADDRESS, unsigned char DATA)
{
// now combine the register address and the command into one byte:
byte dataToSend = READ_WRITE_ADDRESS | WREG;

// take the chip select low to select the device:
SPI.transfer(dataToSend); //Send register location
SPI.transfer(0x00); //number of register to wr
SPI.transfer(DATA); //Send value to record into register
delayMicroseconds(2);
}

@muhammadhusni777
Copy link

An update would really be great, I just made some further tests.
I'm using now 5 full bridge load cells. So I'm always reading between Pos and Neg Pins. I now had to increase N to 4 compared to 2 before. I cannot explain why, but it makes the hole process alot slower.
I also printed the 4 read values of one Sensor, and the first three are zero or -1 and the 4th has the corret value.
Thank you very much.

#include <ADS126X.h>

ADS126X adc1; // start the class
#define N 4
int d=30;

int chip_select1 = 4; // Arduino pin connected to CS on ADS126X

long voltage1 = 0;
long voltage2 = 0;
long voltage3 = 0;
long voltage4 = 0;
long voltage5 = 0;

int pos_pin1 = 0; // ADS126X pin AIN0, for positive inpu
int neg_pin1 = 1;

int pos_pin2 = 2; 
int neg_pin2 = 3; 

int pos_pin3 = 4; 
int neg_pin3 = 5; 

int pos_pin4 = 6; 
int neg_pin4 = 7; 

int pos_pin5 = 8; 
int neg_pin5 = 9; 

int neg_pinInt = ADS126X_REF_POS_INT;
unsigned long us = 0;
unsigned long diff = 0;

void setup() {
  Serial.begin(2000000);
  adc1.begin(chip_select1); // setup with chip select pin0.
  adc1.setRate(ADS126X_RATE_38400);
  adc1.setGain(ADS126X_GAIN_32);
  adc1.startADC1(); // start conversion on ADC1
  Serial.println("Reading Voltages:");
}
void loop() {
 // us = micros();

 for(int i = 0; i < N; i++) {
   voltage1 = adc1.readADC1(pos_pin1,neg_pin1); // read the voltage
   voltage1 =voltage1>>16;
   delayMicroseconds(d); 
 }
 Serial.print(voltage1); // send voltage through serial
 Serial.print(",");


 for(int i = 0; i < N; i++) {
   voltage2 = adc1.readADC1(pos_pin2,neg_pin2); // read the voltage
   voltage2 =voltage2>>16;
   delayMicroseconds(d);
 }
 Serial.print(voltage2); // send voltage through serial.
 Serial.print(",");

 for(int i = 0; i < N; i++) {
   voltage3 = adc1.readADC1(pos_pin3,neg_pin3); // read the voltage
   voltage3 =voltage3>>16;
   delayMicroseconds(d); 
 }
 Serial.print(voltage3); // send voltage through serial
 Serial.print(",");
 
 for(int i = 0; i < N; i++) {
   voltage4 = adc1.readADC1(pos_pin4,neg_pin4); // read the voltage
    voltage4 =voltage4>>16;
   delayMicroseconds(d); 
 }
 Serial.print(voltage4); // send voltage through serial
 Serial.print(",");

 for(int i = 0; i < N; i++) {
   voltage5 = adc1.readADC1(pos_pin5,neg_pin5); // read the voltage
    voltage5 =voltage5>>16;
   delayMicroseconds(d); 
 }
 Serial.println(voltage5); // send voltage through serial
// Serial.print(",");
// diff=micros() - us;
// Serial.println(diff);
   
} 

hello friends. let me know where is the pin start connect to arduino

@domtisdell
Copy link

A short add here to ask if anyone has a neat solution to this problem yet?
Any help will be appreciated. Thanks.

@SammyRamone
Copy link

A short add here to ask if anyone has a neat solution to this problem yet?
Any help will be appreciated. Thanks.

We are currently using it with a dummy read, then waiting 250us and doing the actual read. This works for us, but is obviously not optimal.
You can see our code here https://github.com/bit-bots/bit_foot/blob/master/firmware/esp32_bit_foot/esp32_bit_foot.ino
Hope that helps you

@domtisdell
Copy link

Thanks for the reference SR.

@thisdp
Copy link

thisdp commented Mar 29, 2021

I encounter the same problem, and I solve this by using : while(!(voltage = adc.readADC1(1,2)));
just wait ADC

@halmos
Copy link

halmos commented Nov 4, 2021

I believe the problem may be related to the fact that the ADC should be stopped before writing to the registers.

In the readADC1() method - when the input mux pins have changed, it attempts to write to the registers while the ADC is running (see https://github.com/Molorius/ADS126X/blob/master/src/ADS126X.cpp#L84-L88) . Based on sample code provided by TI in the reference design design, I have found a solution that works around the issue in the ADS126X library and seems to be a lot faster than the solutions above that wait for a successful conversion.

float readAdcV(int ainPos, int ainNeg)
{

  adc.REGISTER.INPMUX.bit.MUXN = ainNeg;
  adc.REGISTER.INPMUX.bit.MUXP = ainPos;
  adc.writeRegister(ADS126X_INPMUX); // replace on ads126x

  adc.startADC1();
  while (digitalRead(esp32AdcRdyPin) == HIGH)
  {
    // wait
  }
  adc.stopADC1();

  signed long int outputCode = adc.readADC1(ainPos, ainNeg);
 
  float voltage = (float)((adcResolution) * (double)(outputCode));
  Serial.print(" outputCode: " + String(outputCode));

  return voltage;
}

where adc is an instance of the ADS126X class. The key is that the ADS126X_INPMUX register is set while the ADC is stopped. TI's sample code also stops the ADC before reading the last conversion -- i have followed that pattern here, though I'm not certain if that is required.

The ADS126X::readADC1 method could be patched to avoid this clunky workaround, but I'm not sure what the software alternative would be to polling the DRDY pin.

@Molorius
Copy link
Owner

Hi everyone, thank you for your patience and feedback. I have a potential fix, I would like help testing it before I clean up the timings and merge into mainline (I no longer have access to this ADC): https://github.com/Molorius/ADS126X/tree/pin-switch-fix

git clone -b pin-switch-fix https://github.com/Molorius/ADS126X.git

This uses the suggestion by @halmos to stop any adc conversions before switching pins. I also decoupled the pin switching from actually reading voltage measurements. You can still use the old syntax though.

If it appears completely broken, please also try either the example in the project for a single read or your own code. I'm pretty sure this code didn't break anything but I cannot test it.

Example 1 (uses old syntax):

#include <ADS126X.h>

ADS126X adc; // start the class

int chip_select = 5; // Arduino pin connected to CS on ADS126X

int pos_pin_first = 0; // ADS126X pin AIN0, for positive input
int neg_pin_first = 1; // ADS126X pin AIN1, for negative input

int pos_pin_second = 2;
int neg_pin_second = 3;

void setup() {
  Serial.begin(115200);
  
  adc.begin(chip_select); // setup with chip select pin
  adc.startADC1(); // start conversion on ADC1
  
  Serial.println("Reading Voltages:");
}

void loop() {
  long voltage_first = adc.readADC1(pos_pin_first,neg_pin_first); // read the voltage for one set of pins
  long voltage_second = adc.readADC1(pos_pin_second,neg_pin_second); // read the voltage for the other set

  Serial.println(voltage_first);
  Serial.println(voltage_second);
  Serial.println("");
  delay(1000); // wait 1 second
}

Example 2 (uses new syntax):

#include <ADS126X.h>

ADS126X adc; // start the class

int chip_select = 5; // Arduino pin connected to CS on ADS126X

int pos_pin_first = 0; // ADS126X pin AIN0, for positive input
int neg_pin_first = 1; // ADS126X pin AIN1, for negative input

int pos_pin_second = 2;
int neg_pin_second = 3;

void setup() {
  Serial.begin(115200);
  
  adc.begin(chip_select); // setup with chip select pin
  adc.startADC1(); // start conversion on ADC1
  
  Serial.println("Reading Voltages:");
}

void loop() {
  adc.setInputMux1(pos_pin_first,neg_pin_first); // set pins to use for reads
  long voltage_first = adc.readADC1(); // read the voltage

  adc.setInputMux1(pos_pin_second,neg_pin_second); // switch reading to different pins
  long voltage_second = adc.readADC1(); // read the voltage

  Serial.println(voltage_first);
  Serial.println(voltage_second);
  Serial.println("");
  delay(1000); // wait 1 second
}

@TheRedFolder
Copy link

Hi Molorius

Thx for you're library and time/effort to make them better :)
I have tested you're examples, and got the following results.

Example 1, gives the result:
Reading Voltages:
0
0

Reading Voltages:
0
0

-1
-1

-1
-1

-1
0

-1
-1

And so on, so the problem is still there.

Example 2, cant compile. The code cant read the following lines:
adc.setInputMux1(pos_pin_first,neg_pin_first); // set pins to use for reads
adc.setInputMux1(pos_pin_second,neg_pin_second); // switch reading to different pins

The setInputMux1, does not works.

@SammyRamone
Copy link

Example 2, cant compile. The code cant read the following lines: adc.setInputMux1(pos_pin_first,neg_pin_first); // set pins to use for reads adc.setInputMux1(pos_pin_second,neg_pin_second); // switch reading to different pins

The setInputMux1, does not works.

Did you make sure that you are on the correct branch (pin-switch-fix). Looks a bit like you may just were on master.

@franz6ko
Copy link

franz6ko commented Aug 2, 2022

I did some testing on the pin-switch-fix but I'm getting 0 readings every 2/3 readings on all channels (I'm working with a 1ms loop reading 4 of the 10 channels of the ADC). Also, that branch introduced delays when stopping or starting the ADC when the mux changes, which I need to happen 4 times on each main loop.

Using the workaround of reading each channel twice with a 250us delay in-between I get an effective loop period of 1.7 ms. On the other hand, using the pin-switch-fix branch I get an effective loop period of ~800ms !!! due to the delays introduced.

The best I've achieved for reading 4 sensors is using the double reading hack of @SammyRamone with a 140us delay and the 38400 rate config. I get a 1.3 ms period for all 4 sensors which is 770Hz

@franz6ko
Copy link

franz6ko commented Aug 2, 2022

Hi everybody, I did more digging and I discovered some surprises about the ADS126X. In general, multiplexed ADCs introduce some delays when changing the multiplexor. Those delays are the reason why the double reading with an in-between delay hack works (it gives time to the multiplexor to change and generate a new reading).

The best way to take this into the account in the library from my perspective would be to use the DRDY (data ready) pin as follows:

  1. Change multiplexor.
  2. Wait for DRDY to be high.
  3. Effectively reading the ADC.

IMPORTANT: however after reading some forums and the datasheet, if your application needs reading more than one channel on each application loop (which I think everyone buying an ADC with more than one channel would be doing...) you will have these multiplexor delays on every loop literally killing the sample rate. With one channel you might get the announced 38400 kSps but in these cases the better you can get is around 1~3 kSps. In conclusion, non-sense...

References: Link 1 | Link 2

@vaibhavvk
Copy link

Hello all,
Thanks @Molorius for this awesome library.
Thanks @franz6ko for the coming up with the suggestion.

Below is my implementation for reading multiple channels. I have implemented a simple function which monitors the DRDY function. I needed to read the values twice from ADC for some reason.

@Molorius sir, I think it will be great if you can implement the DRDY Pin functionality internally in the library.

#include <ADS126X.h>

ADS126X adc; // start the class

int chip_select = 10; // Arduino pin connected to CS on ADS126X
int start_pin = 9;
int drdy_pin = 3;

int pos_pin = 0; // ADS126X pin AIN0, for positive input
//int pos_pin = ADS126X_AIN0;

int neg_pin = 1; // ADS126X pin AIN1, for negative input
//int neg_pin = ADS126X_AIN1;

float last_voltage;
float voltage0_1, voltage2_3;
int drdy_status = 1;


float readADCVal(int pospin, int negpin){
  while(1)
  {
    last_voltage = adc.readADC1(pospin, negpin); // read the voltage
    drdy_status = digitalRead(drdy_pin);
    last_voltage = adc.readADC1(pospin, negpin); // read the voltage
    
    if(drdy_status == 0) break;
  }

  return last_voltage;
}

void setup() {
  Serial.begin(115200);
  
  pinMode(drdy_pin, INPUT_PULLUP);

  adc.setStartPin(start_pin);

  adc.begin(chip_select); // setup with chip select pin

  adc.setGain(ADS126X_GAIN_16);

  adc.setRate(ADS126X_RATE_7200);

  adc.startADC1(); // start conversion on ADC1
  
  Serial.println();
  Serial.println("Reading Voltages:");

}

void loop() {

  voltage0_1 = readADCVal(0, 1);
  voltage2_3 = readADCVal(2, 3);
  

  // adc.lastChecksum();// Check last values error 0 means good

  Serial.print(voltage0_1/100000); // send voltage through serial
  Serial.print("    ");
  Serial.println(voltage2_3/100000); // send voltage through serial
  // delayMicroseconds(1000); // wait 1 second
  delay(1);
}

@bibhu223
Copy link

bibhu223 commented Jun 10, 2024

ADS 1263
https://www.waveshare.com/wiki/High-Precision_AD_HAT
I have this ADS 1263 , I am trying to read the the signal using Arduino nano . But in the adc above there no start pin?

@bibhu223
Copy link

Thank you @Molorius @ziatajo @ziatajo @SammyRamone , for this nice communication , I was try with the code which @Molorius post for multi-channel reading, but the problem I am facing is when my sensor value is increasing in one channel , the value of other also changing , also when my sensor signal coming back to zero, the value in the adc is taking so much time to come back to the original value, ? anyone has a solution for this , or any methods for this problem? i want to read 5 channels at at time.

@Ari-L1000
Copy link

Looks like the library still lacks a consistent way to update ADS1262 settings.

I faced this issue when trying to switch back and forth reading the internal temperature of ADS1262 [adc.readADC1(ADS126X_TEMP, ADS126X_TEMP)] and reading strain gauge [adc.readADC1(ADS126X_AIN7 ,ADS126X_AIN6)].

Reading the temperature requires using internal reference and PGA=1.
Reading strain gauge requires using external reference and PGA=16.
So several settings need to be changed when switching.

I have tried the solutions given earlier in this thread but can't get them to work.

Is there any news about how get this to work?

@Ari-L1000
Copy link

ADS1262 data sheet seems to give instructions how to change the settings. Is it so that the library does not follow this workflow?

image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet