Problem adding multiple sensors
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
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?
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.
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.
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.
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);
}
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 :)
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).
Do you get the same problem with both of ContinuousMode and PulseMode?
How do I change that? :)
You can go to README.md and find setContinuousMode() or setPulseMode()
And pls also try to use this func void setDelay(uint8_t del) to see if it can solve something!
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:");
}
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)
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
Hi, Do you have any other ideas, how I could solve this?
Thank you.
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)
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)
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)
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.
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);
}
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
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?
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
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.
@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"?
Any updates to this? Would be nice to have a real fix without the double readings
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);
}
Sorry for being annoying, but it would still be great to have a fix for this :)
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.
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.
-
You start the
int32_t ADS126X::readADC1(uint8_t pos_pin,uint8_t neg_pin)withif(cs_used) _ads126x_write_pin_low(cs_pin);However, as soon as the pos/neg - pins are changed, you callADS126X::writeRegister(ADS126X_INPMUX);this function callsvoid 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 theif((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 beforeif(cs_used) _ads126x_write_pin_low(cs_pin); -
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).
- 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.