3

TL;DR When trying to use some pins of my ESP32 to read analog signals, it turns out those pins have a non-zero voltage, messing up the measurements. Why?

I got myself an Olimex ESP32-POE-ISO (see specs) to run the irrigation of my garden. I am attaching some hunter valves on GPIO0-5 and the plan was to hook up 3 moisture/temperature sensors (Truebner SMT50) to the pins on the other side of the module (see pinout).

However, I ended up pulling my hair out. On some pins (e.g. GPIO14/ADC2_CH6, GPIO32/ADC1_CH4, GPIO33/ADC1_CH5, GPI35/ADC1_CH7) I get proper readings. I've tried both features (moisture and temperature) of each of the 3 sensors on those pins and the values I get look reasonable. So I am ruling out defective sensors.

I have also tried GPIO13/ADC2_CH4, GPIO15/ADC2_CH3, GPI36/ADC1_CH0, GPIO0/ADC2_CH1 and GPIO2/ADC2_CH2, but I always get numbers that are way to high (raw values at 12bit between 2400-3400, corresponding to voltage 1.9V - 2.7V). And in fact, after disconnecting the sensor and measuring with a multimeter I could find that those pins actualy do have such a voltage (measured against the GND pin) while the "good" pins do not have that.

The initialization code looks like this (channel.channel.adc1_id and ...adc2_id contains values like ADC1_CHANNEL_0, ...):

void SensorService::init() {
    ESP_LOGI(TAG, "Initializing sensor service");

    adc1_config_width(ADC_WIDTH_BIT_12);
    sensorToChannel = getChannelMapping();
    for( const auto& [ idx, channel ] : sensorToChannel) {
        switch (channel.unit) {
            case ADC_UNIT_1:
                adc1_config_channel_atten(channel.channel.adc1_id, ADC_ATTEN_11db);
                break;
            case ADC_UNIT_2:
                adc2_config_channel_atten(channel.channel.adc2_id, ADC_ATTEN_11db);
                break;
            default:
                ESP_LOGW(TAG, "Invalid ADC unit requested");
                break;
        };
    }
}

The reading of raw values like this:

std::optional<unsigned int> SensorService::getRawValue(unsigned int sensorIdx) {
    ESP_LOGV(TAG, "Getting raw value for sensor %d", sensorIdx);

    if (!this->isValidSensorIdx(sensorIdx)) {
        ESP_LOGW(TAG, "Requested non-existing sensor");
        return std::nullopt;
    }

    TargetChannel target = sensorToChannel.at(sensorIdx);
    switch (target.unit) {
        case ADC_UNIT_1:
            return std::make_optional(adc1_get_raw(target.channel.adc1_id));
        case ADC_UNIT_2:
            int value;
            adc2_get_raw(target.channel.adc2_id, ADC_WIDTH_BIT_12, &value);
            return std::make_optional(value);
        default:
            ESP_LOGW(TAG, "Invalid ADC unit requested");
            return std::nullopt;
    }
}

And this works perfectly fine for some pins but not for others.

I also tried a few things I could find in the docs to set the pin explicitly to INPUT and low. But it didn't change anything.

    for (auto const& [ sensorIdx, pin ] : sensorPins) {
        gpio_pad_select_gpio(pin);
        gpio_set_direction(pin, GPIO_MODE_INPUT);
        gpio_set_level(pin, 0);
    }

I am powering and connecting to the board via Ethernet/POE. I am not (knowingly) activating WIFI, RTC, hall sensor anywhere in the code. Not using SD card nor the flash memory for data storage. The values will only be polled via HTTP/Ethernet.

So, my actual question here is, why do some pins (e.g. GPI36, explicitly documented as input-only pin) have non-zero voltage while others haven't? What am I missing?

ErosC
  • 133
  • 4

2 Answers2

3

It looks like several of the pins have pull-ups on them on the board.

If you look at the schematic, you'll see in the UEXT section:

enter image description here

That there are pull-ups on GPIO16, GPI36, GPIO13 and GPIO5. So this explains the results you see on GPI36 and GPIO13.

GPIO0 also has a pull-up (in the ESP-WROOM-32 MODULE section). GPIO15 and GPIO2 have one each in the SD/MMC Card section.

There are quite a few more pull-ups here and there. Looks like there aren't many pins floating on the board. Also see the Notes section at the bottom of the schematic for additional pull-up/down info related to bootstrapping.

jcaron
  • 2,408
  • 5
  • 10
1

Please note that the SMT50 voltage outputs have an output resistance of 10 kOhm (see SMT50 datasheet So if there is a pullup resistance to 3.3V then you will always get voltage levels which are too high. Good to know about the pullups since I plan to start with an ESP32 irrigation control project and SMT50. I will choose the pins without pullup.

Maria
  • 11
  • 1