[SOLVED] Output on wrong channel ONLY with STM32

ZeroX
Mon Jun 25, 2018 5:08 pm
Hello folks,
I have a Problem with the Adafruit ADS1115 16-bit I2C ADC (https://learn.adafruit.com/adafruit-4-c … s/overview) which gives me the output on the wrong channel but only when using the STM32.

OS:Windwos
IDE: Arduino
Board: common blue pill with STM32F103C8

My wiring:
VDD to 3.3 V
GND to GND
SCL to SCL
SDA to SDA
ADDR to GND (resulting in an I2C address of 0x48)
A0 to GND
A1 to GND
A2 to GND
A3 to 3.3 V

I’m not doing differential measuring the connecting of the A-pins to GND and 3.3V is just for testing purpose. Different voltages from any power source result in the same error.
When I connect A3 to a voltage I get a reading for A0. When I connect A0 to a voltage I get a reading for A1. When I connect A1 I get a reading for A2 and so on.

I tried a different ADS1115 which resulted in the same error.
Do you see any flaws in my code? I basically just copied the code from Adafruit (https://learn.adafruit.com/adafruit-4-c … duino-code)

When i try the exact same wiring with an Arduino Nano the outputs are correct!.

That’s really strange because the sensor library is the same and the protocol is I2C therefore it can’t be a wiring error on the STM32 board.

I appreciate any help.

Many thanks in advance!

#include "Wire.h"
#include "Adafruit_ADS1015.h" //library for ADS1015 and ADS1115

Adafruit_ADS1115 ads1115(0x48);

void setup()
{
while (!Serial);
delay(1000);
Wire.begin();
Serial.begin(115200);

ads1115.begin(); // Initialize ads1115
}

void loop() {

int16_t adc0, adc1, adc2, adc3;

adc0 = ads1115.readADC_SingleEnded(0);
adc1 = ads1115.readADC_SingleEnded(1);
adc2 = ads1115.readADC_SingleEnded(2);
adc3 = ads1115.readADC_SingleEnded(3);
Serial.print("AIN0: "); Serial.println(adc0);
Serial.print("AIN1: "); Serial.println(adc1);
Serial.print("AIN2: "); Serial.println(adc2);
Serial.print("AIN3: "); Serial.println(adc3);
Serial.print("\n \n ");

delay(1000);
}


Pito
Mon Jun 25, 2018 5:31 pm
Try with
uint32_t adc0, adc1, adc2, adc3;

ZeroX
Mon Jun 25, 2018 5:54 pm
Thanks for the super fast reply!

I will try it soon.

The ADS1115 parametrics talk about a maximum analog voltage of 5.5V http://www.ti.com/product/ADS1115

Best regards

ZeroX


Pito
Mon Jun 25, 2018 7:10 pm
The 1115’s max voltage at the ADC inputs is from GND (0.0V) to Vdd (3.3V in your case).

ZeroX
Mon Jun 25, 2018 9:00 pm
Unfortunately changing int16_t to int 32_t did not solve the problem.

heisan
Mon Jun 25, 2018 9:38 pm
I haven’t read the datasheet, but from the library, it looks like a timing issue… Try replace every ADC read with channel 0, so that all four reads are:
ads1115.readADC_SingleEnded(0);

If this reads channel 0 correctly, then try change the code so all 4 read from channel 1 – if it then reads from channel 1, then it is almost certainly a timing issue.


zoomx
Tue Jun 26, 2018 10:50 am
Since the function is
uint16_t readADC_SingleEnded(uint8_t channel);

Pito
Tue Jun 26, 2018 11:01 am
Also double check the library itself. In past I had an issue with a BMP180 library – the 8bit arduino’s libs are using int/long with different sizes than we use here..

PS: could you confirm you get correct ADC values based on the applied input voltages (even at different inputs)??
Post an example here – input voltage and the value you get.


stevestrong
Tue Jun 26, 2018 11:06 am
Which core is here involved? Libmaple or ST or generic?

heisan
Tue Jun 26, 2018 11:47 am
The mux config is two bits in the middle of an 8 bit write. For them to be corrupted in such a way that the binary value of those 2 bits always ends up as 1 less than the expected value is implausible. BUT the library does not check the conversion status bit – it just waits 8ms and reads the conversion register. If the conversion has not completed yet, it will read the result of the previous conversion (i.e. input A0 when reading channel A1).

Looking at the libmaple implementation of delay(8), it will delay somewhere between 7 and 8 ms (but mostly less than 8ms) which could result in such an error.


Pito
Tue Jun 26, 2018 12:44 pm
Interestingly the 1115 has got 8 different sample rates (8 – 860 samples per sec). Waiting 8ms for the result does match maybe the 64 one.
I am using the 1110 with a different library, it adjusts the waiting based on sample rate (4 rates), however.
As this is a delta sigma ADC the duration of a conversion differs with the “sample/data rate”
The ADS111x offer programmable output data rates. Use the DR[2:0] bits in the Config register to select output data rates of 8 SPS, 16 SPS, 32 SPS, 64 SPS, 128 SPS, 250 SPS, 475 SPS, or 860 SPS. Conversions in the ADS111x settle within a single cycle; thus, the conversion time is equal to 1 / DR.
Also the ADC’s data size differs with sample rate (with 1110) from 16 to 12bits afaik. Not sure how it is with 1115..

zoomx
Tue Jun 26, 2018 2:45 pm
[heisan – Tue Jun 26, 2018 11:47 am] –
BUT the library does not check the conversion status bit – it just waits 8ms and reads the conversion register. If the conversion has not completed yet, it will read the result of the previous conversion (i.e. input A0 when reading channel A1).

This seem a good point!


ZeroX
Tue Jun 26, 2018 3:46 pm
Many thanks for all the help you guys give me!
I try work through your ideas step by step.

@heisan
I Changed all readings to ads1115.readADC_SingleEnded(0) and indeed the program presented the value on the intended. How can I solve a timing issue like this? My program needs to be as fast as possible. 10-100 readings per second from about 24 Analog inputs of 5 ADS1115.

@zoomx
I checked all channels and the error occurred always in the same way. Readings on A0 -> value given for A1, Readings on A1 -> value given for A2, …, A3->A0. Did you mean that with “check all the channels?”

@Pito
I get following values for the connections:
Ground ~0
no connection 3000-33000
3.3 Volt 15800-16600
These are the value ranges of about 5 different measurements (rested the microcontroller every time by disconnecting it from power supply)
Every channels shows more or less the same result.

@stevestrong
It is the generic core

@heisan again
“The mux config is two bits in the middle of an 8 bit write. For them to be corrupted in such a way that the binary value of those 2 bits always ends up as 1 less than the expected value is implausible. BUT the library does not check the conversion status bit – it just waits 8ms and reads the conversion register.”

I didn’t understand everything you wrote here (I’m new to the subject sorry)
What is:
mux config? With “corrupted” you mean an error that occurs from bad connection? What is an “conversion status bit”?

This community is awesome.
Looking forward to your answers.

Best regards
ZeroX


heisan
Tue Jun 26, 2018 4:02 pm
[ZeroX – Tue Jun 26, 2018 3:46 pm] –
Many thanks for all the help you guys give me!
I try work through your ideas step by step.

In your Libraries folder, find ‘Adafruit_ADS1X15/Adafruit_ADS1015.h’ and edit:

#define ADS1115_CONVERSIONDELAY (8)

to be:

#define ADS1115_CONVERSIONDELAY (9)

and see if that fixes the problem?


ZeroX
Tue Jun 26, 2018 4:14 pm
@heisan

It worked!!!!!

But for my understanding what exactly have i done?

Thank you so much, all of you!


heisan
Tue Jun 26, 2018 4:29 pm
[ZeroX – Tue Jun 26, 2018 4:14 pm] –
@heisan

It worked!!!!!

But for my understanding what exactly have i done?

Thank you so much, all of you!

The Adafruit_ADS1X15 library writes a ‘read ADC’ command to the ADS1115, then waits 8ms (the expected time the ADC will take for the conversion) then reads the conversion result register from the ADC. If the conversion is not yet complete, then it ends up reading the *previous* conversion result.

There looks like a bug in the STM32 core where if you say ‘delay(8)’ it will delay between 7 and 8ms, but the ADC requires 8ms, so it reads the old value. The change to the header file makes this ‘delay(9)’ which will delay between 8 and 9ms, so the conversion is complete and the correct value is read.

A better solution would be to update the driver library to poll the conversion complete bit – but that is way too much effort ;) .


ZeroX
Tue Jun 26, 2018 4:34 pm
Now i get it.

I posted this issue on the Arduino and the Adafruit board as well do you mind if i post the fix and mention this board and your name?

Best regards

ZeroX


Pito
Tue Jun 26, 2018 4:39 pm
Those 8/9ms delay will not work with sampling/data rates lower than 128 samples/second (see my above post).
You can do 8 – 840 ADC samples per second. Thus the delay has to be set based on the actual “sampling rate” you want to use. Or better with polling the conversion ready flag..

heisan
Tue Jun 26, 2018 4:44 pm
[ZeroX – Tue Jun 26, 2018 4:34 pm] –
Now i get it.

I posted this issue on the Arduino and the Adafruit board as well do you mind if i post the fix and mention this board and your name?

Best regards

ZeroX

Sure – but as noted, this is not the ‘correct’ solution but rather a workaround.

[Pito – Tue Jun 26, 2018 4:39 pm] –
Those 8/9ms delay will not work with sampling/data rates lower than 128 samples/second (see my above post).
You can do 8 – 840 ADC samples per second. Thus the delay has to be set based on the actual “sampling rate” you want to use.

This specific library has hard-coded sample rate, and pre-calculated delays based on this hard coded sample rate.


Pito
Tue Jun 26, 2018 4:48 pm
I know, that is not good, moreover with 860 samples/sec it is enough to wait 1.2msecs :)
There must be a different library available which is not hard coded.

ZeroX
Tue Jun 26, 2018 6:52 pm
On what depends the sampeling rate?

Baud rate? How fast it takes for the programm to run one loop? A pre selected value in the library?


Pito
Tue Jun 26, 2018 7:04 pm
The sampling rate (ADC measurements/second) depends on the chip used and your library capabilities.
The 1115 chip can do 8-860 measurements per second.
It could be the ADC resolution depends on the sampling rate (double check that).
Your library has to be able to set the sampling rate. You may try to set it to the maximum 860 (but it is probably hard coded). In that case it is enough to have 1/860 sec delay there.
Read the datasheet of your chip, do not rely on the libraries only.

heisan
Tue Jun 26, 2018 7:09 pm
I did a quick google, and this lib looks like it may work better:

https://github.com/baruch/ADS1115


Pito
Tue Jun 26, 2018 7:22 pm
https://github.com/baruch/ADS1115
That lib does not check the conversion ready bit nor waits with that delay, it seems.
It reads in what comes from the chip..
It cannot be difficult to include the conversion readiness, however..

This library polls the conversion ready flag:

https://github.com/addicore/ADS1115/blo … DS1115.cpp


heisan
Tue Jun 26, 2018 8:00 pm
[Pito – Tue Jun 26, 2018 7:22 pm] –
https://github.com/baruch/ADS1115
That lib does not check the conversion ready bit nor waits with that delay, it seems.
It reads in what comes from the chip..
It cannot be difficult to include the conversion readiness, however..

If you look at the sample code, it requires the caller to poll the conversion ready flag, which can be an advantage, as it becomes a non-blocking process.


ZeroX
Tue Jun 26, 2018 8:05 pm
Thank you for all the reply’s. I really appreciate the help I get from you!

I will check those libraries tomorrow and give you feedback as soon as I can.


Pito
Tue Jun 26, 2018 9:09 pm
[heisan – Tue Jun 26, 2018 8:00 pm] –
..If you look at the sample code, it requires the caller to poll the conversion ready flag, which can be an advantage, as it becomes a non-blocking process.

Yea, right, I see it in the example (readme)
if (!adc.is_sample_in_progress()) {


zoomx
Tue Jun 26, 2018 10:23 pm
[ZeroX – Tue Jun 26, 2018 4:14 pm] –
It worked!!!!!

Please add [Solved] at the title argument, best at start.


Leave a Reply

Your email address will not be published. Required fields are marked *