UncleRus / esp-idf-lib

Component library for ESP32-xx and ESP8266
https://esp-idf-lib.readthedocs.io/en/latest/
1.38k stars 428 forks source link

ads111x: 4-channel example (ads1115) and ALRT pin #472

Closed politsin closed 1 year ago

politsin commented 1 year ago

The issue

Привет! Спасибо за отличный набор библиотек. Текущий репозиторий - это самое первое место куда я иду за библиотеками.

Пример использования библиотеки по умолчанию (default) отлично работает. https://github.com/UncleRus/esp-idf-lib/tree/master/examples/ads111x/default Используя код примера считываю данные с A0.

1) Не могу понять как использовать библиотеку для чтения значений с других пинов: A1, A1, A3. Подскажи как мне получить эти значения?

2) Есть небольшое непонимание по блоку с ads111x_is_busy который всегда висит внутри цикла. Я его закомментировал, на данном этапе меня это вполне устраивает.

3) На модулях есть ещё один пин ALRT использование которого нет в примерах. Мы можем послать команду "начать измерение", а считывать измерения уже по прерыванию с этого пина. Возможно даже библиотека уже поддерживает такой режим работы, но моего уровня развития недостаточно чтобы это понять) Абсолютно не критичный для меня вопрос, просто чтобы не забыть - когда то я это использовал. Модуль с алиекспресса с пином ALRT (если это имеет значение) который я использую выглядит так

Навсякий пожарный приложу свой код:

#include <ads111x.h>
#define GAIN ADS111X_GAIN_4V096 // +-4.096V

// I2C addresses 48
static const uint8_t addr = ADS111X_ADDR_GND;
static i2c_dev_t ads;

void ntcTask(void *pvParam) {
  // bool debug = 0;
  static float gain_val;
  gain_val = ads111x_gain_values[GAIN];
  ads111x_init_desc(&ads, addr, I2C_NUM_0, (gpio_num_t)33, (gpio_num_t)25);
  // Continuous conversion mode
  ESP_ERROR_CHECK(ads111x_set_mode(&ads, ADS111X_MODE_CONTINUOUS));
  // 32 samples per second
  ESP_ERROR_CHECK(ads111x_set_data_rate(&ads, ADS111X_DATA_RATE_32));
  // Positive = AIN0, negative = GND.
  ESP_ERROR_CHECK(ads111x_set_input_mux(&ads, ADS111X_MUX_0_GND));
  ESP_ERROR_CHECK(ads111x_set_gain(&ads, GAIN));
  vTaskDelay(pdMS_TO_TICKS(100));
  int16_t raw;
  int32_t celsius;
  while (true) {
    vTaskDelay(pdMS_TO_TICKS(500));
    // bool busy;
    // do {
    //   vTaskDelay(pdMS_TO_TICKS(2 * 100));
    //   ESP_LOGI(NTC_TAG, "ads111x_is_busy");
    //   ads111x_is_busy(&ads, &busy);
    // } while (busy);

    // Read result
    if (ads111x_get_value(&ads, &raw) == ESP_OK) {
      float voltage = 1000 * gain_val * raw / ADS111X_MAX_VALUE;
      celsius = rawNtcToTemperature(voltage);
      ESP_LOGI(NTC_TAG, "Voltage: %.03f mV, celsius= %d", voltage, celsius);
      // debugNotify(raw, celsius, debug);
    } else {
      ESP_LOGI(NTC_TAG, "Cannot read ADC value");
    }
  }
}

Which SDK are you using?

esp-idf

Which version of SDK are you using?

master

Which build target have you used?

Component causing the issue

ads111x

Anything in the logs that might be useful for us?

No response

Additional information or context

No response

Confirmation

UncleRus commented 1 year ago

Привет! Спасибо за теплые слова.

  1. Выбор конфигурации входов для ADS1115 производится при помощи вызова ads111x_set_input_mux() и передачи туда любого значения из перечисления ads111x_mux_t. Допустимые значения:
    typedef enum
    {
    ADS111X_MUX_0_1 = 0, //!< положительный = AIN0, отрицательный = AIN1 (default)
    ADS111X_MUX_0_3,     //!< положительный = AIN0, отрицательный = AIN3
    ADS111X_MUX_1_3,     //!< положительный = AIN1, отрицательный = AIN3
    ADS111X_MUX_2_3,     //!< положительный = AIN2, отрицательный = AIN3
    ADS111X_MUX_0_GND,   //!< положительный = AIN0, отрицательный = GND
    ADS111X_MUX_1_GND,   //!< положительный = AIN1, отрицательный = GND
    ADS111X_MUX_2_GND,   //!< положительный = AIN2, отрицательный = GND
    ADS111X_MUX_3_GND,   //!< положительный = AIN3, отрицательный = GND
    } ads111x_mux_t;

    т.е., для измерения аналогового сигнала на входе, например, AIN3 относительно земли, нужно вызвать

    ads111x_set_input_mux(&dev, ADS111X_MUX_3_GND);
  2. Еще относительно недавно в библиотеке был баг, который при вызове ads111x_is_busy() возвращал инвертированное значение флага занятости чипа :). Обновите локально библиотеку до последнего master-а при помощи git pull и вот кусочек полностью рабочего примера:
    
    ...
    static inline void wait_adc_busy()
    {
    bool busy;
    do
    {
        ESP_ERROR_CHECK(ads111x_is_busy(&adc, &busy));
        if (busy)
            vTaskDelay(1);
    }
    while (busy);
    }

static void task(void *arg) { ... ESP_ERROR_CHECK(ads111x_set_mode(&adc, ADS111X_MODE_SINGLE_SHOT)); while (true) { ESP_ERROR_CHECK(ads111x_start_conversion(&adc)); wait_adc_busy(); ESP_ERROR_CHECK(ads111x_get_value(&adc, &v)); ... } }


3. Для того чтобы использовать вывод ALERT/RDY как сигнал об окончании измерения, согласно даташиту необходимо сделать следующее:
    a) подтянуть вывод  ALERT/RDY к плюсу питания резистором ~10k
    b) перевести чип в режим непрерывных измерений `ads111x_set_mode(&dev, ADS111X_MODE_CONTINUOUS)`
    c) установить нужную частоту измерений, напр. 128Hz: `ads111x_set_data_rate(&dev, ADS111X_DATA_RATE_128)`
    d) установить нормальный режим работы компаратора: `ads111x_set_comp_mode(&dev, ADS111X_COMP_MODE_NORMAL)`
    e) настроить полярность компаратора: `ads111x_set_comp_polarity(&dev, ADS111X_COMP_POLARITY_LOW)`
    f) установить размер очереди компаратора, равный 1: `ads111x_set_comp_queue(&dev, ADS111X_COMP_QUEUE_1)` 
    g) установить специальные значения в регистрах граничных значений компаратора: `ads111x_set_comp_low_thresh(&dev, 0)`  и `ads111x_set_comp_high_thresh(&dev, -1)`
UncleRus commented 1 year ago

В любом случае, прошу Вас в дальнейшем все-таки использовать английский, поскольку вопросы и ответы на них могут быть интересны не только русскозычным, и задавать вопросы в разделе "Discussions" репозитория.

politsin commented 1 year ago

Ого!

Огромное спасибо за такую оперативность!

Вроде всё понятно, пойду дальше ковырять.

По поводу ads111x_is_busy я видел тикет с ошибкой, после скачал свежую библиотеку и проблема всё равно была. Попробую ещё, напишу результат.

Опишу позицию по поводу языка)

Я могу свой текст прогнать через гугл-транслейт или deepl и получить корявый английскйи который потом ещё немного отредактировать перед отрпавкой. Но это будет всё равно очень плохой английский и часть смысла в вопросах обязательно будет потеряна.

По опыту общения с неносителями языка - сильно проще когда они пишут на своём родном языке, тогда мысль выражена ясно. В момент перевода я могу посмотреть значение каждого слова чтобы понять суть. А если человек заранее "позаботился" и прогнал свой текст через автоперевод, а оригинала нет, то докопаться до сути уже нет шанса. Алиекспресс состоит примерно на половину из таких текстов в описании товара.

В текущем тикете:

В современно мире:

В будущем могу вопросы заранее переводить или дублировать на английском, хозяин-барин (вот и идиомы подоспели). Про раздел "Discussions" понял.

Огромное спасибо за вашу работу! Библиотеки прям топ 🔥