Skip to content

esp32: PinInputPullup does not work on some GPIO pins #3477

Open
@bxparks

Description

@bxparks

Summary

Several GPIO pins on the ESP32 do not work with machine.PinInputPullup. It seems like they are configured as PinInput instead. These same pins do work in INPUT_PULLUP mode in C++ under the ESP32 Arduino Core. The problem GPIO pins are:

  • GPIO32, GPIO33, GPIO25, GPIO26, GPIO27, GPIO12, GPIO13, GPIO4, GPIO2.

This is not a high priority, because I can rewire my buttons to use different pins. But it would be nice to make these GPIO pins work as expected.

Environment

  • tinygo version 0.27.0 linux/amd64 (using go version go1.19.3 and LLVM version 15.0.0)
  • ESP32 Arduino Core v2.0.7
  • Arduino IDE 1.8.19
  • microcontroller: ESP32 DevKitV1 (30 pin version), using an ESP-WROOM-32 module
  • command line: $ tinygo flash -x -target=esp32-coreboard-v2

Symptoms

When the above problem GPIO pins are configured using machine.PinInputPullup, the internal pullup resistor does not seem to be connected. The pin.Get() method just returns a stream of false. When I connect an external pullup 10kOhm pullup resistor, the pin.Get() returns true. I am then able to attach an active-low push button to that GPIO pin to read a false (pressed) or true (released).

Those problematic GPIO pin work perfectly fine in INPUT_PULLUP mode using C++ under the ESP32 Arduino Core. No external pullup resistors are necessary to attach a push button to those pins.

I understand that 4 of the GPIO pins on the ESP32 do not have hardware support for INPUT_PULLUP: GPIO34, GPIO35, GPIO36, and GPIO39. Those pins behave the same way under both TinyGo or Arduino C++.

Minimal Reproducible TinyGo Program

package main

import (
  "machine"
  "time"
)

const pin = machine.GPIO13 // Replace this with various GPIO pins

func main() {
  pin.Configure(machine.PinConfig{Mode: machine.PinInputPullup})

  time.Sleep(time.Millisecond * 500)
  print("Reading pin #", pin, ": ")

  for {
    value := pin.Get()
    if value {
      print("1")
    } else {
      print("0")
    }
    time.Sleep(time.Millisecond * 100)
  }
}

Output:

Reading pin #13: 000000000000000000000000000000000000000000000000000000000000000000

Minimal Reproducible Arduino C++ Program

#include <Arduino.h>
const uint8_t PIN = 13;

void setup() {
  Serial.begin(115200);
  pinMode(PIN, INPUT_PULLUP);

  delay(500);
  Serial.print("Reading pin #");
  Serial.print(PIN);
  Serial.print(": ");
}

void loop() {
  uint8_t value = digitalRead(PIN);
  Serial.print(value);
  delay(100);
}

Output:

Reading pin #13: 1111111111111111111111111111111111111111100111110011111

Complete Summary Various Pins on ESP32 DevKit V1

I tested all exposed GPIO pins on my DevKit V1, and collected the results in the table below. The [*] indicates the pins which are observed to behave differently between TinyGo and Arduino C++.

GPIO2 is a strange one. On the DevKit1 that I have, it is connected to an onboard LED. Using Arduino C++, when I configure it to INPUT_PULLUP, I can make it work with a button using a 10kOhm external pullup resistor. However, using TinyGo, I am not able to get this pin working with an external pullup. I'm not really sure what's happening with GPIO2.

ESP32-DOIT-DEVKIT-V1-Pinout-30-GPIOs

+-----+------------+------------------------+------------------------+
|     | Pin        | TinyGo                 | ESP32 Arduino          |
+-----+------------+------------------------+------------------------+
|Boot |            |                        |                        |
|     | GPIO0      | works                  | works                  |
+-----+------------+------------------------+------------------------+
|Left |            |                        |                        |
|     | GPIO36     | works with ext pullup  | works with ext pullup  |
|     | GPIO39     | works with ext pullup  | works with ext pullup  |
|     | GPIO34     | works with ext pullup  | works with ext pullup  |
|     | GPIO35     | works with ext pullup  | works with ext pullup  |
|     | GPIO32 [*] | works with ext pullup  | works                  |
|     | GPIO33 [*] | works with ext pullup  | works                  |
|     | GPIO25 [*] | works with ext pullup  | works                  |
|     | GPIO26 [*] | works with ext pullup  | works                  |
|     | GPIO27 [*] | works with ext pullup  | works                  |
|     | GPIO14     | works                  | works                  |
|     | GPIO12 [*] | works with ext pullup  | works                  |
|     | GPIO13 [*] | works with ext pullup  | works                  |
+-----+------------+------------------------+------------------------+
|Right|            |                        |                        |
|     | GPIO23     | works                  | works                  |
|     | GPIO22     | works                  | works                  |
|     | GPIO1/TX0  | no output              | no output              |
|     | GPIO3/RX0  | works                  | works                  |
|     | GPIO21     | works                  | works                  |
|     | GPIO19     | works                  | works                  |
|     | GPIO18     | works                  | works                  |
|     | GPIO5      | works                  | works                  |
|     | GPIO17/TX2 | works                  | works                  |
|     | GPIO16/RX2 | works                  | works                  |
|     | GPIO4  [*] | works with ext pullup  | works                  |
|     | GPIO2  [*] | always LOW, LED        | works with ext pullup  |
|     | GPIO15     | works                  | works                  |
+-----+------------+------------------------+------------------------+

[*] - difference observed between TinyGo and ESP32 Arduino Core

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingesp32

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions