ADS1115

Нумерация аналоговых входов

Использование цтфро-аналоговых и аналогово-цифровых преобразователей и пользовательских блоков к ним
Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#1

Сообщение Rovki » 02.09.2023{, 13:25}

Столкнулся с несоответствием нумерации аналоговых входов. Проверил даташит и разводку платы - все правильно.
Плата https://aliexpress.ru/item/32817162654. ... 4aa6ZJhYEo
проект-
проект.jpg
схема-
схема ацп.jpg
а вот результат-
результат.jpg
Это передача на панель по модбасу. Пробовал и в уарт передавать - результат тот же .
Пробовал штатный блок и от экойнса - результат тот же .
У кого такой же результат? :smile453:
Электронщик до мозга костей и не только

nic103
Рядовой
Сообщения: 10
Зарегистрирован: 08.12.2016{, 16:56}
Репутация: 0
Откуда: Назарово
Имя: Сергей

ADS1115

#2

Сообщение nic103 » 02.09.2023{, 19:09}

Испытывал подобный девайс но косяка не заметил. Хотел миллиамперметр запилить но падение на шунте 0,1 ом оказалось маловато. Заказал MAX4372TEUK ( Усилители считывания тока) жду, буду дальше экспериментировать. На неделе перепроверю ADS1115, отпишусь.

ivansidor012
Сержант
Сообщения: 279
Зарегистрирован: 10.09.2020{, 14:37}
Репутация: 43
Имя: Иван

ADS1115

#3

Сообщение ivansidor012 » 02.09.2023{, 19:19}

Rovki писал(а):
02.09.2023{, 13:25}
Плата https://aliexpress.ru/item/32817162654. ... 4aa6ZJhYEo

если почитать отзывы, то там фуфло перемаркированное:

Модуль получен упакованным в запаянном электростатическом пакете. Но на плате вместо ADS1115 (официальная маркировка BOGI) установлен какой-то китайский чип с маркировкой ADX111A. В сети о нем данных нет! Подключил этот модуль к тестовой Ардуине - вроде показывает правильно при работе с библиотекой Adafruit_ADS1X15 - задействованы все 16 бит. Отмечен в 2 раза больший шум по сравнению с оригиналом. Походу китайцы и ADS1115 научились как-то импортозамещать

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#4

Сообщение Александр » 02.09.2023{, 20:36}

Rovki писал(а):
02.09.2023{, 13:25}
Столкнулся с несоответствием нумерации аналоговых входов. Проверил даташит и разводку платы - все правильно.
Настройте блок на получение значения только! одного канала, другие выключите - предполагаю(судя по даташиту и библиотеке), что получите правильные данные. Иначе какая-то дичь...

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#5

Сообщение Rovki » 02.09.2023{, 20:49}

Александр писал(а):
02.09.2023{, 20:36}
Rovki писал(а):
02.09.2023{, 13:25}
Столкнулся с несоответствием нумерации аналоговых входов. Проверил даташит и разводку платы - все правильно.
Настройте блок на получение значения только! одного канала, другие выключите - предполагаю(судя по даташиту и библиотеке), что получите правильные данные. Иначе какая-то дичь...
мне нужно получать данные с 16 каналов (4 ADS)

Отправлено спустя 44 секунды:
ivansidor012 писал(а):
02.09.2023{, 19:19}
Rovki писал(а):
02.09.2023{, 13:25}
Плата https://aliexpress.ru/item/32817162654. ... 4aa6ZJhYEo

если почитать отзывы, то там фуфло перемаркированное:

Модуль получен упакованным в запаянном электростатическом пакете. Но на плате вместо ADS1115 (официальная маркировка BOGI) установлен какой-то китайский чип с маркировкой ADX111A. В сети о нем данных нет! Подключил этот модуль к тестовой Ардуине - вроде показывает правильно при работе с библиотекой Adafruit_ADS1X15 - задействованы все 16 бит. Отмечен в 2 раза больший шум по сравнению с оригиналом. Походу китайцы и ADS1115 научились как-то импортозамещать
есть данные https://datasheet.lcsc.com/lcsc/2302211 ... 359372.pdf
там все аналогично с ads1115

Отправлено спустя 6 минут 34 секунды:
Похоже тут найдена причина (библиотека) и решение .Почему то зависит от процессора (быстродействие его), из-за буферизации в ADS :smile37: .У меня ЕСП32
https://forums.adafruit.com/viewtopic.php?t=137450
Электронщик до мозга костей и не только

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#6

Сообщение Александр » 02.09.2023{, 21:48}

Rovki писал(а):
02.09.2023{, 20:56}
мне нужно получать данные с 16 каналов (4 ADS)
Речь шла об эксперименте.
Rovki писал(а):
02.09.2023{, 20:56}
Похоже тут найдена причина (библиотека) и решение .Почему то зависит от процессора (быстродействие его), из-за буферизации в ADS .У меня ЕСП32
Как я и предполагал, проблема в библиотеке.
У микросхемы один регистр данных, и считывать его нужно после окончания преобразования. Когда Вы будете считывать только одним канал, проблемы не будет с адресом входа, т.к. запрос и считывание будет по одному входу. Подход, желателен, как у 18B20 - отправили запрос, спустя время, гарантированно большее времени преобразования, считали и отправили новый адрес канала. ИМХО.

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#7

Сообщение Rovki » 02.09.2023{, 21:51}

Только как узнать ,что преобразование окончено ? Тем более мне нужна скорость опроса 200гц. :smile453:

Отправлено спустя 6 минут 34 секунды:
а закономерность видна четко- всегда читаются данные с прошлого канала 0-3,1-0,2-1,3-2 и так по кругу.. :smile427:
Электронщик до мозга костей и не только

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#8

Сообщение Александр » 02.09.2023{, 21:58}

Вариантов несколько, но под Ваши требования подходит несколько - работа на 400 и опрос регистра готовности или использование выхода 1115:
Еще одной полезной функцией компаратора является оповещение по окончании преобразования, для включения которого необходимо установить старший бит регистра Hi_thresh в 1, а старший бит регистра Lo_thresh в 0. В этом случае бит активного уровня COMP_POL, а также бит управления компаратором COMP_QUE продолжают действовать, биты COMP_MODE и COMP_LAT не влияют на выход компаратора.

Если функция оповещения включена, то в режиме непрерывного преобразования, после окончания каждого измерения на выходе компаратора появляется импульс длительностью 8 мкс. В режиме одиночного преобразования на выходе компаратора устанавливается низкий логический уровень по окончании преобразования, если бит COMP_POL установлен в 0. Тем самым эту функцию удобно использовать в качестве прерывания для управляющего устройства, чтобы не опрашивать постоянно бит OS, а сразу считывать результат преобразования.
Rovki писал(а):
02.09.2023{, 21:57}
а закономерность видна четко- всегда читаются данные с прошлого канала 0-3,1-0,2-1,3-2 и так по кругу..
С одним каналом будет ок.

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#9

Сообщение Rovki » 02.09.2023{, 21:59}

Там очень много модификаций ads - разные скорости преобразования , на чипе надпись не разобрать

Отправлено спустя 4 минуты 13 секунд:
А как задать (узнать) частоту опроса ? (Программируемая частота образцов: от 8 до 860 образцов/сек)

Отправлено спустя 1 минуту 30 секунд:
Александр писал(а):
02.09.2023{, 21:58}
Вариантов несколько, но под Ваши требования подходит несколько - работа на 400 и опрос регистра готовности или использование выхода 1115:
Еще одной полезной функцией компаратора является оповещение по окончании преобразования, для включения которого необходимо установить старший бит регистра Hi_thresh в 1, а старший бит регистра Lo_thresh в 0. В этом случае бит активного уровня COMP_POL, а также бит управления компаратором COMP_QUE продолжают действовать, биты COMP_MODE и COMP_LAT не влияют на выход компаратора.

Если функция оповещения включена, то в режиме непрерывного преобразования, после окончания каждого измерения на выходе компаратора появляется импульс длительностью 8 мкс. В режиме одиночного преобразования на выходе компаратора устанавливается низкий логический уровень по окончании преобразования, если бит COMP_POL установлен в 0. Тем самым эту функцию удобно использовать в качестве прерывания для управляющего устройства, чтобы не опрашивать постоянно бит OS, а сразу считывать результат преобразования.
Rovki писал(а):
02.09.2023{, 21:57}
а закономерность видна четко- всегда читаются данные с прошлого канала 0-3,1-0,2-1,3-2 и так по кругу..
С одним каналом будет ок.
Для одного канала я бы использовал АЦП ЕСП32
Электронщик до мозга костей и не только

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#10

Сообщение Александр » 02.09.2023{, 22:29}

Rovki писал(а):
02.09.2023{, 20:56}
мне нужно получать данные с 16 каналов (4 ADS)
Rovki писал(а):
02.09.2023{, 21:57}
Тем более мне нужна скорость опроса 200гц.
Блок с использованием вывода ADS ALERT/RDY должен быть примерно таким:
один раз: настраиваются конф. регистры, разрешается работа по n каналу прерывания, отправляется запрос на считывание канала - запоминается адрес(индекс).
далее по прерыванию:
считываются данные в массив по индексу, при этом мс выключит сигнал окончания преобразования, адрес(индекс) увеличивается, отправляется новый запрос.
Для опроса след. мс после окончания предыдущей, обработка прерывания на одном входе отключаются, на другом вкл.
Остальное по ходу.
Но конкретно в Вашем случае, много каналов, я бы обратил внимание на работу с микросхемами, работающими по SPI, существенно быстрей и проще.
Главный вопрос - разрядность и частота обновления, есть ещё stm32 с двумя 12 бит ацп.

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#11

Сообщение Rovki » 03.09.2023{, 07:02}

Только где взять такой блок? :smile427:

Отправлено спустя 2 минуты 47 секунд:
Скорости работы интерфейса I2C (100/400) более чем достаточно .Все определяется быстродействием самого АЦП :smile37:. Использую 4х4 АЦП

Отправлено спустя 5 минут 5 секунд:
На всякий случай заказал и такие https://aliexpress.ru/item/400075184832 ... 7122621001
8 каналов по 24 бита разрядность
Электронщик до мозга костей и не только

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#12

Сообщение Александр » 03.09.2023{, 14:11}

Rovki писал(а):
03.09.2023{, 07:10}
Скорости работы интерфейса I2C (100/400) более чем достаточно .Все определяется быстродействием самого АЦП . Использую 4х4 АЦП
Примем алгоритм следующего формата для четырёх мс -
считываем данные предыдущего запроса мс1;
отправка данных для следующего канала мс1;
считываем данные предыдущего запроса мс2;
отправка данных для следующего канала мс2;
и т.д.
Рассчитаем время, ориентировочно, на один канал: пять байт на считывание + четыре байта на запись = 9 байт.
При 100к 9 байт займут примерно, округлим, 1мс.
Соответственно, спустя "круг" в мс 1115 будут уже готовые данные при Data rate 860SPS, беспокоится не о чем.
Но, при 1 мс мы получим на все каналы 1000SPS - соответственно, о 16 каналах и 200"Гц" говорить не приходится.
Увеличив до 400k - будет, возможно, но на пределе.
Это так, рассуждения выходного дня...

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#13

Сообщение Rovki » 03.09.2023{, 14:36}

Может не точно выразился, меня не заботит задержка получения данных. Через 5 мс получим данные с одного АЦП ( 4 канала) , через ещё 5 со второго, итд.. Тогда на 4ацп будет 20мс ... Пойдёт. Мне достаточно снимать с переменных резисторов 1000 значений на канал за время 10 сек. И так по 16 каналам пусть с задержкой ... Это для испытательного стенда подстроечных резисторов. На каждый резистор 2 канала. Один мерит и расчитывает номинал, второй снимает характеристику при вращении.
Электронщик до мозга костей и не только

ivansidor012
Сержант
Сообщения: 279
Зарегистрирован: 10.09.2020{, 14:37}
Репутация: 43
Имя: Иван

ADS1115

#14

Сообщение ivansidor012 » 03.09.2023{, 15:30}

Rovki,
Александр писал(а):
03.09.2023{, 14:11}
соответственно, о 16 каналах и 200"Гц" говорить не приходится
Rovki писал(а):
03.09.2023{, 15:30}
Скорости работы интерфейса I2C (100/400) более чем достаточно
останется только библиотеку переписать - вопрос кто возьмется и во сколько обойдется

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#15

Сообщение Rovki » 03.09.2023{, 16:19}

Для знающих час работы :smile225:

Отправлено спустя 3 минуты 57 секунд:
Есть биб-ки для работы по прерываниям
https://github.com/GolinskiyKonstantin/ ... /README.md
Электронщик до мозга костей и не только

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#16

Сообщение Александр » 03.09.2023{, 18:03}

Rovki писал(а):
03.09.2023{, 16:23}
Для знающих час работы
Немного было времени на даче, код никак не тестировался, вообще, возможны недочёты!

Код: Выделить всё

#include <Wire.h>
uint16_t config_1115 = 0xC3E3;  // первичная конфигурация, AI-0, 4,096 В

void setup(){         
  Wire.begin();         
  for(int16_t a=0; a<4; a++){ // Первичная инициализация, не обязательна.
    Wire.beginTransmission(0x48 | a);
    Wire.write(0x01);
    Wire.write((uint8_t)(config_1115 >> 8));
    Wire.write((uint8_t)(config_1115 & 0xFF));
    Wire.endTransmission();
  }
}
void loop(){

  int16_t data_array[16]; // данные без конверсии, чистые данные АЦП, 1 = 0,000125v, 
  // конвертировать во float (real) перед непосредственным использованием
  int16_t adr1115;
  int16_t chanel1115;
  // цикл для 100k
  for (int16_t i=0; i<16; i++){
    adr1115 = 0x48 | (i & 0x03);  // готовим адрес
    // читаем данные из предыдущего запроса
    Wire.beginTransmission(adr1115);
    Wire.write(0x00);
    Wire.endTransmission();
    Wire.requestFrom(adr1115, 2);
    data_array[i] =  (Wire.read() << 8) | Wire.read(); // данные без конверсии!!!
    // даём команду на следующее преобразование, изменив номер канала в конф. регистре
    chanel1115 = (i>>2 + 1) & 0x03;
    config_1115 = 0xC3E3 | chanel1115 << 12;
    Wire.beginTransmission(adr1115);
    Wire.write(0x01);
    Wire.write((uint8_t)(config_1115 >> 8));
    Wire.write((uint8_t)(config_1115 & 0xFF));
    Wire.endTransmission();   
  }

}

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#17

Сообщение Rovki » 03.09.2023{, 20:22}

Спасибо, Александр. Попробую, отпишусь :smile9:

Отправлено спустя 12 минут 34 секунды:
Александр, ,будьте добры, добавьте вывод на монитор значений каналов 1-4 (номер канала+ значение). Компиляция проходит без ошибок
Электронщик до мозга костей и не только

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#18

Сообщение Александр » 03.09.2023{, 21:08}

Rovki, Какие каналы, с какой мс/адреса. Код для 16 каналов, 4х4.

Аватара пользователя
Rovki
Полковник
Сообщения: 4877
Зарегистрирован: 22.04.2016{, 17:25}
Репутация: 268
Откуда: Чехов
Имя: Анатолий
Контактная информация:

ADS1115

#19

Сообщение Rovki » 03.09.2023{, 21:14}

Александр писал(а):
03.09.2023{, 21:08}
Rovki, Какие каналы, с какой мс/адреса. Код для 16 каналов, 4х4.
Для одной ADS(4 канала-А0, А1,А2,А3), адрес 48. Что бы проверить код визуально
Подключить можно только 4 ADS (48,49,50,51)

Отправлено спустя 8 минут 27 секунд:
Вот код работает правильно со штатной библиотекой
#include <Adafruit_ADS1X15.h>

Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
//Adafruit_ADS1015 ads; /* Use this for the 12-bit version */

void setup(void)
{
Serial.begin(115200);
Serial.println("Hello!");

Serial.println("Getting single-ended readings from AIN0..3");
Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)");

// The ADC input range (or gain) can be changed via the following
// functions, but be careful never to exceed VDD +0.3V max, or to
// exceed the upper and lower limits if you adjust the input range!
// Setting these values incorrectly may destroy your ADC!
// ADS1015 ADS1115
// ------- -------
// ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default)
ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV
// ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV
// ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV
// ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV
// ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV

if (!ads.begin()) {
Serial.println("Failed to initialize ADS.");
while (1);
}
}

void loop(void)
{
int16_t adc0, adc1, adc2, adc3;
float volts0, volts1, volts2, volts3;

adc0 = ads.readADC_SingleEnded(0);
adc1 = ads.readADC_SingleEnded(1);
adc2 = ads.readADC_SingleEnded(2);
adc3 = ads.readADC_SingleEnded(3);

volts0 = ads.computeVolts(adc0);
volts1 = ads.computeVolts(adc1);
volts2 = ads.computeVolts(adc2);
volts3 = ads.computeVolts(adc3);

Serial.println("-----------------------------------------------------------");
Serial.print("AIN0: "); Serial.print(adc0); Serial.print(" "); Serial.print(volts0); Serial.println("V");
Serial.print("AIN1: "); Serial.print(adc1); Serial.print(" "); Serial.print(volts1); Serial.println("V");
Serial.print("AIN2: "); Serial.print(adc2); Serial.print(" "); Serial.print(volts2); Serial.println("V");
Serial.print("AIN3: "); Serial.print(adc3); Serial.print(" "); Serial.print(volts3); Serial.println("V");

delay(1);
}
Электронщик до мозга костей и не только

Александр
Рядовой
Сообщения: 72
Зарегистрирован: 01.12.2015{, 15:49}
Репутация: 11
Откуда: Бобруйск
Имя: Александр

ADS1115

#20

Сообщение Александр » 03.09.2023{, 21:24}

Код: Выделить всё



#include <Wire.h>
uint16_t config_1115 = 0xC3E3;  // первичная конфигурация, AI-0, 4,096 В

void setup(){         
  Wire.begin();         
  for(int16_t a=0; a<4; a++){ // Первичная инициализация, не обязательна.
    Wire.beginTransmission(0x48 | a);
    Wire.write(0x01);
    Wire.write((uint8_t)(config_1115 >> 8));
    Wire.write((uint8_t)(config_1115 & 0xFF));
    Wire.endTransmission();
  }
  Serial.begin(38400);
}
void loop(){

  int16_t data_array[16]; // данные без конверсии, чистые данные АЦП
  int16_t adr1115;
  int16_t chanel1115;
  // цикл для 100k
  for (int16_t i=0; i<16; i++){
    adr1115 = 0x48 | (i & 0x03);  // готовим адрес
    // читаем данные из предыдущего запроса
    Wire.beginTransmission(adr1115);
    Wire.write(0x00);
    Wire.endTransmission();
    Wire.requestFrom(adr1115, 2);
    data_array[i] =  (Wire.read() << 8) | Wire.read(); // данные без конверсии!!!
    // даём команду на следующее преобразование, изменив номер канала в конф. регистре
    chanel1115 = (i>>2 + 1) & 0x03;
    config_1115 = 0xC3E3 | chanel1115 << 12;
    Wire.beginTransmission(adr1115);
    Wire.write(0x01);
    Wire.write((uint8_t)(config_1115 >> 8));
    Wire.write((uint8_t)(config_1115 & 0xFF));
    Wire.endTransmission();   
  }
  for( int16_t s=0; s<4; s++){
	Serial.println("Chanel " + String(s*4) + " = " + String(float(data_array[s*4] * 0,000125),6));	// *4 для данных из 1 мс
  }
  // delay(500);

}
Возможно так?

Ответить

Вернуться в «ЦАП и АЦП»