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

add functionality to use multiple ads1115's on one i2cbus #5083

Merged
merged 5 commits into from
Feb 8, 2019
Merged

add functionality to use multiple ads1115's on one i2cbus #5083

merged 5 commits into from
Feb 8, 2019

Conversation

kevinbaluha
Copy link
Contributor

by setting up an array of flags and restructuring the output code you can now have up to 4 ads115's on one i2c bus.

@andrethomas
Copy link
Contributor

andrethomas commented Feb 1, 2019

Whilst you are busy with changing the driver, is it possible for you to make the detection routine a bit more robust by reading specific registers such as documented in the datasheet

9.6.4Lo_thresh(P[1:0]= 2h) [reset= 8000h]and Hi_thresh(P[1:0]= 3h) [reset= 7FFFh]Registers

and confirm that you get returned values of 0x8000 and 0x7FFF respectively to validate a detect on the specific I2C address as opposed to just finding "something" on the I2C address.

Would be an enhancement because currently if you use sonoff-sensors.bin with a LM75AD connected the device also gives a false detect of a ADS1115 because it uses overlapping I2C addresses.

The LM75AD driver was already updated to include such a change to avoid false detects but it would be good to have this on the ADS1115 also.

I would do it myself but I cannot confirm functionality because I do not have an ADS1115 yet.

Thanks

@arendst arendst added the awaiting feedback Action - Waiting for response or more information label Feb 1, 2019
@kevinbaluha
Copy link
Contributor Author

kevinbaluha commented Feb 1, 2019 via email

@demian85
Copy link

demian85 commented Feb 2, 2019

I was wondering if any of you guys can help me with the ads1115 setup.
I want to use one to read between 0-5v analog input from a MQ-135 sensor but I don't understand how to configure the comparator min-max values. How do I know then how to interpret the digital values?
Thanks!

@kevinbaluha
Copy link
Contributor Author

kevinbaluha commented Feb 2, 2019 via email

@andrethomas
Copy link
Contributor

@demian85 The comparator is only if you want to set thresholds on the ADS1115 and have them output a logic state/trigger on the ALERT pin so it has no direct use from Tasmota. For obtaining a value from a 5V signal I would recommend using a voltage divider from the 5V side to get it close to 3.3V.

Perhaps to give a common range using 1.2k and 2.2k resistors you can obtain a 0 to 3.235V range with a 0 to 5V input range in the following configuration

image

To convert the obtained value back to a 5V range you can multiply the result of the ADC by 5/3.235.

@ascillato2 ascillato2 added the enhancement Type - Enhancement that will be worked on label Feb 3, 2019
@Frogmore42
Copy link
Contributor

For measuring sensors that have 5V outputs with an ADS1115, you have two choices.

  1. You can do what @andrethomas suggested and use a resistor voltage divider

  2. You can run the ADS1115 at 5V and use an I2C compatible level shifter

Since the sensor you have selected needs a specific load attached to it, you will likely get better results with the 2nd option. But, since the sensor you have selected is not known to be particularly accurate or consistent, either method should get you fairly equivalent results.

@demian85
Copy link

demian85 commented Feb 3, 2019

I don't understand what you are saying. Why would I need a voltage divider if this ADC supports up to 6.144v? I just wanted to know how to read digital values from the ADS1115 sensor, and turns out I only needed to do some math.

This is what I am doing to calculate the voltage (source: http://henrysbench.capnfatz.com/henrys-bench/arduino-voltage-measurements/arduino-ads1115-module-getting-started-tutorial/)
voltage = (ADS1115.A0 * 0.1875) / 1000;

And then I can calculate the "air quality" percentage using the rule of three (not really accurate, but to get some human-friendly number)
airQuality = 100 - Math.round((100 * voltage) / 5)

@Frogmore42
Copy link
Contributor

Read the data sheet more closely. The ADC inputs can only go up to the power rail +0v3, so 3v6 for a 3v3 supply. You can set the full scale to 6.44, but you will likely destroy the part if you apply that.

@demian85
Copy link

demian85 commented Feb 4, 2019 via email

@andrethomas
Copy link
Contributor

Is there anything wrong with what I am doing?

If the ADS1115 is powered from 5V then you're good to go except for the interface between the ADS1115 and ESP8266 which will require level shifting to ensure interoperability at 3.3V level for SCL and SDA pins used on the ESP8266.

I have connected 5V i2c devices to D1 and D2 on the ESP8266 before without any adverse implications but I'm reluctant to recommend this because it may just have worked in my use-case by pure chance.

If you google around a bit there does seem to be varied opinions on whether or not the GPIO pins are 5V tolerant so its safer to stick to 3.3V unless you don't mind risking the loss of a ESP8266 chip - For me this did not matter as I have a cache of replacement chips which I could swap out if need be but like I said i have never needed to do this.

@demian85
Copy link

demian85 commented Feb 4, 2019

lol you are right, I completely forgot about the I2c communication. Somehow I thought it used 3.3v no matter what.
What happens if I have more than one device in the bus that used 3.3v? Can I mix 5v and 3.3v devices in a I2c bus?
If not, can I use a voltage regulator between the 5V sensor and the I2c lines?
I got this one https://en.wikipedia.org/wiki/78xx

Thanks!

@andrethomas
Copy link
Contributor

andrethomas commented Feb 4, 2019

You need to use level shifting boards similar to this https://www.banggood.com/3Pcs-Two-Channel-IIC-I2C-Logic-Level-Converter-Bi-Directional-Module-p-979923.html - This is just an example so you should be able to find similar/same ones at a local hobby electronics store or from ali express etc...

Use case video https://www.youtube.com/watch?v=ze-dD9D94F8

@kevinbaluha
Copy link
Contributor Author

kevinbaluha commented Feb 6, 2019 via email

@Frogmore42
Copy link
Contributor

For level shifting the NXP and Phillips app notes are literally the book on the technique. This is a part that does that
https://www.adafruit.com/product/757

For selecting the device for a particular i2c address, that is not as easy as it might first appear. There are different devices that can have the same address, so the current method does not always work. But, for commonly used sensors, it works surprisingly well. If you have a better way to do it, please submit a PR.

@kevinbaluha
Copy link
Contributor Author

I have updated this code so that up to 4 (the max addresses) can be connected to the i2c bus at once . i have added a read config check in the 1115 code and a read ID register in the tsl2561 code to improve detection.
I believe its ready for review and merging.

@andrethomas
Copy link
Contributor

andrethomas commented Feb 7, 2019

@kevinbaluha Thanks for taking the time to make the PR and looking into the changes required mitigating false detects.

It can work in its current form... I am not sure if you tested the detection routine as previously suggested which may look something like this to confirm a positive detect... not sure if its too nested for @arendst :)

void Ads1115Detect(void)
{
  uint16_t buffer;

  for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) {
    if (!ads1115_found[i]) { // We're not going to scan this address again if we already have a detect on it
      ads1115_address = ads1115_addresses[i];
      if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_LOWTHRESH)) {
        if (0x8000 == buffer) {
          if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_HITHRESH)) {
            if (0x7FFF == buffer) {
              Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN);
              ads1115_type = 1;
              ads1115_found[i] = 1;
              snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address);
              AddLog(LOG_LEVEL_DEBUG);
            }
          }
        }
      }
    }
  }
}

Nice spotting the TSL2561 as a potential conflict! Thx

@kevinbaluha
Copy link
Contributor Author

kevinbaluha commented Feb 7, 2019

I looked at doing that but instead opted at I2cValidRead16(&conf_buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG) to read the config. I think this will catch 99.9 percent false detection.
and is smaller.

@andrethomas
Copy link
Contributor

@kevinbaluha Thanks, I just cleaned it up a little bit :)

@arendst This one is ready for you...

@arendst arendst merged commit f587510 into arendst:development Feb 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting feedback Action - Waiting for response or more information enhancement Type - Enhancement that will be worked on
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants