Molorius / ADS126X

A class for the TI ADS1262 and ADS1263
38 stars 20 forks source link

Problem adding multiple sensors #5

Open ziatajo opened 5 years ago

ziatajo commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

ziatajo commented 5 years ago

How do I change that? :)

q-bird commented 5 years ago

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

q-bird commented 5 years ago

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

ziatajo commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

Thank you.

q-bird commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago
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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

@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 commented 5 years ago

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

ziatajo commented 5 years ago

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 commented 5 years ago

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

Molorius commented 5 years ago

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 commented 4 years ago

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 commented 4 years ago

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

nravirke commented 4 years ago

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

SammyRamone commented 4 years ago

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 commented 4 years ago

Hi, Pl Try This Program..

// DATE: 09 06 2020 AT 20:23 // R K ENTERPRISES // RAVI N //ravirke@gmail.com /*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

include

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 commented 3 years ago

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 commented 3 years ago

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

SammyRamone commented 3 years ago

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 commented 3 years ago

Thanks for the reference SR.

thisdp commented 3 years ago

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

halmos commented 3 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 5 months ago

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 commented 4 months ago

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 commented 4 months ago

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 commented 3 weeks ago

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 commented 3 weeks ago

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