This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tamiwiki:users:6r1d:diymall_esp32_s3_fixture [2025/10/18 17:49] – 6r1d | tamiwiki:users:6r1d:diymall_esp32_s3_fixture [2025/10/20 05:43] (current) – [ESP-IDF (+ history and PWM debug)] 6r1d | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | There's something | + | There’s something |
| - | Or a bad board. Mostly | + | Or a non-working one. |
| + | //Usually// it's one of those two. | ||
| - | And I've been using a fixture by [[http:// | + | ====== Introduction ====== |
| + | |||
| + | I've been using a fixture by [[http:// | ||
| {{: | {{: | ||
| - | It is very helpful as a fixture. It is not helpful whatsoever | + | It is very helpful as a fixture. It is not helpful whatsoever |
| So, the fixture is easy to buy on AliExpress, for example, [[https:// | So, the fixture is easy to buy on AliExpress, for example, [[https:// | ||
| Thus, I've traced everything I found so you don't have to. | Thus, I've traced everything I found so you don't have to. | ||
| + | |||
| + | ====== Pin assignments ====== | ||
| ^ ESP32-S3-Wroom contact pad ^ Datasheet reference ^ Arduino pin ^ Board pin ^ | ^ ESP32-S3-Wroom contact pad ^ Datasheet reference ^ Arduino pin ^ Board pin ^ | ||
| Line 41: | Line 46: | ||
| | 37 | TXD0 | 37 | D34 | | | 37 | TXD0 | 37 | D34 | | ||
| - | If you'd like to make corrections or are unhappy | + | ===== Notes ===== |
| + | |||
| + | * GPIO pin 48 is the onboard LED, usually blue. | ||
| + | * Initially, I thought that onboard USB-UART is connected to something else than RXD0 / TXD0. It was not. It is the main UART. | ||
| + | |||
| + | ====== Tracing code ====== | ||
| + | |||
| + | You might disagree with me and want to double-check. Excellent! More eyes (and feedback) mean better information. | ||
| + | |||
| + | Grab your trusty 30-year-old LED soldered to a pair of DuPont sockets and start tracing. | ||
| + | |||
| + | For convenience, | ||
| + | ===== ESP-IDF (+ history and PWM debug) ===== | ||
| + | |||
| + | This code gives you a predictable interactive workflow with history. | ||
| + | |||
| + | < | ||
| + | > help | ||
| + | Commands: | ||
| + | list -> show test-safe GPIOs | ||
| + | status | ||
| + | pin < | ||
| + | < | ||
| + | delay < | ||
| + | pwm <pin> [brightness] | ||
| + | brightness < | ||
| + | freq < | ||
| + | stop -> stop and release pin | ||
| + | |||
| + | > 48 | ||
| + | Stopped. Pin released to INPUT. | ||
| + | Blinking GPIO 48 at 100 ms. | ||
| + | |||
| + | > 42 | ||
| + | Stopped. Pin released to INPUT. | ||
| + | Blinking GPIO 42 at 100 ms. | ||
| + | |||
| + | > 47 | ||
| + | Stopped. Pin released to INPUT. | ||
| + | Blinking GPIO 47 at 100 ms. | ||
| + | |||
| + | > 46 | ||
| + | Restricted: GPIO 46 is not in the test-safe set. | ||
| + | |||
| + | > delay 40 | ||
| + | Set blink delay to 40 ms. | ||
| + | |||
| + | > delay 10 | ||
| + | Set blink delay to 10 ms. | ||
| + | </ | ||
| + | |||
| + | As for using it, you should know the gist at this point. | ||
| + | |||
| + | <code bash> | ||
| + | mkdir pin_tracer && cd pin_tracer | ||
| + | idf.py create-project . && idf.py reconfigure && idf.py set-target esp32s3 | ||
| + | # fill the code | ||
| + | # update the CMake configs | ||
| + | idf.py build | ||
| + | idf.py flash monitor | ||
| + | </ | ||
| + | |||
| + | For your convenience, | ||
| + | |||
| + | Clone it like that: | ||
| + | |||
| + | <code bash> | ||
| + | git clone https:// | ||
| + | </ | ||
| + | |||
| + | Also, you can use Minicom to interact with the tracing code if you'd like. It's just one of the default baudrates, 115200. | ||
| + | |||
| + | <code bash> | ||
| + | minicom -D / | ||
| + | </ | ||
| + | ===== Arduino (basic version) ===== | ||
| + | |||
| + | Flash from Arduino IDE. Use the ESP32 board package by Espressif, pick ESP32S3 Dev Module, pick 115200 baud in Serial Monitor. | ||
| + | |||
| + | <file cpp esp32_s3_pin_tracer.ino> | ||
| + | #include < | ||
| + | |||
| + | // ====== CONFIG ====== | ||
| + | // Blink timing (change at runtime with: delay < | ||
| + | static uint32_t BLINK_DELAY_MS = 100; | ||
| + | |||
| + | // Conservative " | ||
| + | // Excludes pins that commonly serve boot strapping, USB D-/D+, PSRAM/ | ||
| + | // which can interfere with programming, | ||
| + | // | ||
| + | // Notes (summarized from the ESP32-S3 module/chip docs): | ||
| + | // - 0, 3, 45, 46 are strapping/ | ||
| + | // - 19, 20 are the on-chip USB D-/D+ differential pair; toggling them breaks USB comms. | ||
| + | // - 35, 36, 37 are wired to Octal PSRAM on some variants; not available as GPIO there. | ||
| + | // - 43 (U0TXD), 44 (U0RXD) are UART0 console pins used by Serial; poking them disrupts logs/ | ||
| + | // - 47, 48 form a differential SPI clock pair; safe as GPIO but mind 1.8 V I/O level on some R16V variants. | ||
| + | const uint8_t TEST_SAFE_GPIO[] = { | ||
| + | 1, 2, // ADC/ | ||
| + | 4, 5, 6, 7, // " | ||
| + | 8, 9, 10, 11, 12, 13, 14, // " | ||
| + | 15, 16, 17, 18, // " | ||
| + | // 19,20 excluded (USB D-/D+) | ||
| + | 21, // plain GPIO | ||
| + | // 22..34 don't exist on S3 modules | ||
| + | // 35,36,37 excluded (PSRAM on some variants) | ||
| + | 38, 39, 40, 41, 42, // JTAG-capable if configured, but OK as GPIO when JTAG is not in use | ||
| + | // 43,44 excluded (UART0 TX/RX used by Serial) | ||
| + | 47, 48 // differential clock pair; OK as GPIO (watch 1.8 V I/O on some R16V variants) | ||
| + | }; | ||
| + | const size_t TEST_SAFE_GPIO_COUNT = sizeof(TEST_SAFE_GPIO) / sizeof(TEST_SAFE_GPIO[0]); | ||
| + | |||
| + | // ====== RUNTIME STATE ====== | ||
| + | static int currentPin = -1; | ||
| + | static bool blinking = false; | ||
| + | |||
| + | // ====== HELPERS ====== | ||
| + | bool isTestSafe(int gpio) { | ||
| + | for (size_t i = 0; i < TEST_SAFE_GPIO_COUNT; | ||
| + | if ((int)TEST_SAFE_GPIO[i] == gpio) return true; | ||
| + | } | ||
| + | return false; | ||
| + | } | ||
| + | |||
| + | void printTestSafePins() { | ||
| + | Serial.println(F(" | ||
| + | for (size_t i = 0; i < TEST_SAFE_GPIO_COUNT; | ||
| + | Serial.print(F(i ? ", " : " | ||
| + | Serial.print(TEST_SAFE_GPIO[i]); | ||
| + | } | ||
| + | Serial.println(); | ||
| + | Serial.println(F(" | ||
| + | } | ||
| + | |||
| + | void stopBlink() { | ||
| + | if (currentPin >= 0) { | ||
| + | digitalWrite(currentPin, | ||
| + | pinMode(currentPin, | ||
| + | } | ||
| + | blinking = false; | ||
| + | currentPin = -1; | ||
| + | Serial.println(F(" | ||
| + | } | ||
| + | |||
| + | void startBlink(int gpio) { | ||
| + | if (!isTestSafe(gpio)) { | ||
| + | Serial.print(F(" | ||
| + | Serial.print(gpio); | ||
| + | Serial.println(F(" | ||
| + | return; | ||
| + | } | ||
| + | if (blinking && currentPin == gpio) { | ||
| + | Serial.print(F(" | ||
| + | Serial.println(gpio); | ||
| + | return; | ||
| + | } | ||
| + | // switch pin if needed | ||
| + | if (blinking && currentPin != gpio) stopBlink(); | ||
| + | |||
| + | currentPin = gpio; | ||
| + | pinMode(currentPin, | ||
| + | digitalWrite(currentPin, | ||
| + | blinking = true; | ||
| + | |||
| + | Serial.print(F(" | ||
| + | Serial.print(currentPin); | ||
| + | Serial.print(F(" | ||
| + | Serial.print(BLINK_DELAY_MS); | ||
| + | Serial.println(F(" | ||
| + | } | ||
| + | |||
| + | // Parse commands like: | ||
| + | // | ||
| + | // pin 10 | ||
| + | // delay 250 | ||
| + | // | ||
| + | void handleCommand(String line) { | ||
| + | line.trim(); | ||
| + | if (line.length() == 0) return; | ||
| + | |||
| + | line.toLowerCase(); | ||
| + | if (line == " | ||
| + | printTestSafePins(); | ||
| + | return; | ||
| + | } | ||
| + | if (line == " | ||
| + | stopBlink(); | ||
| + | return; | ||
| + | } | ||
| + | if (line.startsWith(" | ||
| + | int gpio = line.substring(4).toInt(); | ||
| + | startBlink(gpio); | ||
| + | return; | ||
| + | } | ||
| + | if (line.startsWith(" | ||
| + | int v = line.substring(6).toInt(); | ||
| + | if (v < 10) v = 10; // clamp a bit | ||
| + | BLINK_DELAY_MS = (uint32_t)v; | ||
| + | Serial.print(F(" | ||
| + | Serial.print(BLINK_DELAY_MS); | ||
| + | Serial.println(F(" | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | // Single-number shortcut: just type the GPIO number | ||
| + | bool allDigits = true; | ||
| + | for (size_t i = 0; i < (size_t)line.length(); | ||
| + | if (!isDigit(line[i])) { | ||
| + | allDigits = false; | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | if (allDigits) { | ||
| + | startBlink(line.toInt()); | ||
| + | return; | ||
| + | } | ||
| + | |||
| + | Serial.println(F(" | ||
| + | Serial.println(F(" | ||
| + | Serial.println(F(" | ||
| + | Serial.println(F(" | ||
| + | Serial.println(F(" | ||
| + | Serial.println(F(" | ||
| + | } | ||
| + | |||
| + | void setup() { | ||
| + | Serial.begin(115200); | ||
| + | // give USB-Serial/ | ||
| + | delay(400); | ||
| + | Serial.println(F(" | ||
| + | Serial.println(F(" | ||
| + | printTestSafePins(); | ||
| + | } | ||
| + | |||
| + | void loop() { | ||
| + | // Process serial line input | ||
| + | static String line; | ||
| + | while (Serial.available()) { | ||
| + | char c = (char)Serial.read(); | ||
| + | if (c == ' | ||
| + | if (c == ' | ||
| + | handleCommand(line); | ||
| + | line = ""; | ||
| + | } else { | ||
| + | line += c; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // Blink the selected pin | ||
| + | if (blinking && currentPin >= 0) { | ||
| + | digitalWrite(currentPin, | ||
| + | delay(BLINK_DELAY_MS); | ||
| + | digitalWrite(currentPin, | ||
| + | delay(BLINK_DELAY_MS); | ||
| + | } else { | ||
| + | delay(5); | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | |||
| + | ====== Feedback ====== | ||
| + | |||
| + | |||
| + | If you’d like to suggest | ||
| - | This topic possibly deserves | + | This topic might deserve |
| + | Then again, | ||