Share My Creation Searching pin on stranger board

If you investigate the unknown PCB without any circuit diagram - it needs to detect what GPIO is used for LEDs, or relay or other activity part.
Let's try:

1. Determine the MCU
2. Find the list of the MCU pins: note, if some danger (strapping) pin is in the list - MCU can just restart during the pins initialization.
3. Serial UART interface is not always available, it can be availabe only, say, at powering up with the pressed BOOT-button (GPIO0 at ESP32-family of MCU) - so the Morse code will help ;)
4. After start be ready to press the BOOT button when you catch the LED blink or relay click: the sketch will hold the latest used GPIO number after you pressed the button. And next will blink it by the Morse code.


B4X:
#Region Project Attributes
#AutoFlushLogs: True
#CheckArrayBounds: True
#StackBufferSize: 300
#End Region

'Sketch for testing MCU ports with output of port number in Morse code

Sub Process_Globals
    Public Serial1 As Serial
    'Active level configuration
    Public const ACTIVE_HIGH As Boolean = False 'true - active level HIGH, false - active level LOW
   
    'List of ports to test (excluding strapping pins and GPIO0), setup for your MCU
    Public testPins() As Byte = Array As Byte(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45, 46, 47, 48)
    Public numTestPins As Int
   
    Dim pinButton As Pin
    Public const buttonPin As Byte = 0 'Button on GPIO0
    Public const pinActivationTime As ULong = 300 '300ms port activation time for visibility
    Public const pauseTime As ULong = 2000 '2 seconds pause for manual button clicking when seen the activity
   
    Public selectedLedPin As Int = -1 'Memorized LED port
    Public buttonPressed As Boolean = False

    'Logging counters
    Private testCycleCount As Int = 0
End Sub

Private Sub AppStart
    Serial1.Initialize(115200)
    Delay(3000)
    Log("=== ESP32-S3 Port Testing Utility ===")
    Log("Initializing...")
    Log("Active Level: ", IIf(ACTIVE_HIGH, "HIGH", "LOW"))
    Log("Number of test pins: ", testPins.Length)
    Log("Button pin: GPIO", buttonPin)
    Log("Starting in 5 seconds...")
   
    numTestPins = testPins.Length
   
    'Initialize all test ports as OUTPUT
    Log("Initializing GPIO pins as OUTPUT...")
    For i = 0 To numTestPins - 1
        Dim p As Pin
        p.Initialize(testPins(i), p.MODE_OUTPUT)
        setPinState(testPins(i), False) 'Turn off all ports
        Log("GPIO ", testPins(i), " initialized")
    Next
   
    'Button initialization
    pinButton.Initialize(buttonPin, pinButton.MODE_INPUT_PULLUP)
    Log("Button initialized on GPIO", buttonPin)
   
    '5 second pause after start
    Delay(5000)
    Log("=== Starting port testing sequence ===")
   
    'Main loop
    Do While True
        'If port is not yet selected, perform testing
        If selectedLedPin = -1 Then
            testCycleCount = testCycleCount + 1
            Log("--- Test Cycle #", testCycleCount, " ---")
            testAllPins
        Else
            Log("=== PORT SELECTED: GPIO", selectedLedPin, " ===")
            Log("Starting Morse code transmission...")
            'Blink the selected port number in Morse code
            sendNumberMorse(selectedLedPin)
            Log("Morse transmission completed. Pausing for 10 seconds...")
            Delay(10000) '10 second pause between repetitions
        End If
    Loop
End Sub

Sub testAllPins
    For i = 0 To numTestPins - 1
        Dim currentPin As Byte = testPins(i)
       
        Log("Testing GPIO", currentPin, " (", i + 1, "/", numTestPins, ")")
       
        'Activate port
        setPinState(currentPin, True)
        Log("GPIO", currentPin, " ACTIVATED")
       
        'Wait for activation time with button polling
        Dim startTime As ULong = Millis
        Dim buttonCheckCount As Int = 0
        Do While Millis - startTime < pinActivationTime
            checkButton(currentPin)
            If buttonPressed Then
                Log("BUTTON PRESSED DETECTED during activation!")
                Exit
            End If
            buttonCheckCount = buttonCheckCount + 1
            Delay(10)
        Loop
       
        'Deactivate port
        setPinState(currentPin, False)
        Log("GPIO", currentPin, " DEACTIVATED")
       
        'If button is pressed, interrupt testing
        If buttonPressed Then
            Log("=== TESTING INTERRUPTED ===")
            Log("Selected port: GPIO", selectedLedPin)
            Log("Pausing for 5 seconds before Morse transmission...")
            Delay(5000) '5 second pause
            Return
        End If
       
        'Pause between ports
        Log("Pausing for ", pauseTime, "ms...")
        startTime = Millis
        buttonCheckCount = 0
        Do While Millis - startTime < pauseTime
            checkButton(currentPin)
            If buttonPressed Then
                Log("BUTTON PRESSED DETECTED during pause!")
                Exit
            End If
            buttonCheckCount = buttonCheckCount + 1
            Delay(10)
        Loop
       
        If buttonPressed Then
            Log("=== TESTING INTERRUPTED ===")
            Log("Selected port: GPIO", selectedLedPin)
            Log("Pausing for 5 seconds before Morse transmission...")
            Delay(5000) '5 second pause
            Return
        End If
       
        Log("GPIO", currentPin, " test completed")
    Next
    Log("--- Cycle #", testCycleCount, " completed ---")
End Sub

Sub checkButton(currentPin As Byte)
    If pinButton.DigitalRead = False Then 'Button pressed (LOW due to PULLUP)
        Log("[BUTTON] Initial press detected on GPIO", currentPin)
        Delay(50) 'Debounce
        If pinButton.DigitalRead = False Then    'still pressed
            selectedLedPin = currentPin
            buttonPressed = True
            Log("[BUTTON] CONFIRMED - GPIO", currentPin, " selected!")
            Log("[BUTTON] Button pressed: ", buttonPressed)
            Log("[BUTTON] Selected LED pin: ", selectedLedPin)
        Else
            Log("[BUTTON] Debounce failed - false trigger")
        End If
    End If
End Sub

Sub sendNumberMorse(number As Int)
    Log("[MORSE] Transmitting number: ", number)
    'Split number into digits and transmit them sequentially
    If number < 10 Then
        'Single-digit number
        Log("[MORSE] Single digit: ", number)
        sendDigitMorse(number, selectedLedPin)
    Else
        'Two-digit number - transmit first digit, then second
        Dim firstDigit As Int = number / 10
        Dim secondDigit As Int = number Mod 10
        Log("[MORSE] Two digits: ", firstDigit, " and ", secondDigit)
       
        sendDigitMorse(firstDigit, selectedLedPin)
        Log("[MORSE] Pause between digits...")
        Delay(2000) 'Pause between digits (2 seconds)
        sendDigitMorse(secondDigit, selectedLedPin)
    End If
    Log("[MORSE] Transmission completed for number: ", number)
End Sub

Sub sendDigitMorse(digit As Int, pin As Byte)
    Log("[MORSE] Sending digit: ", digit, " on GPIO", pin)
    Select digit
        Case 0 ' -----
            Log("[MORSE] Digit 0: -----")
            dash(pin): dash(pin): dash(pin): dash(pin): dash(pin)
        Case 1 ' .----
            Log("[MORSE] Digit 1: .----")
            dot(pin): dash(pin): dash(pin): dash(pin): dash(pin)
        Case 2 ' ..---
            Log("[MORSE] Digit 2: ..---")
            dot(pin): dot(pin): dash(pin): dash(pin): dash(pin)
        Case 3 ' ...--
            Log("[MORSE] Digit 3: ...--")
            dot(pin): dot(pin): dot(pin): dash(pin): dash(pin)
        Case 4 ' ....-
            Log("[MORSE] Digit 4: ....-")
            dot(pin): dot(pin): dot(pin): dot(pin): dash(pin)
        Case 5 ' .....
            Log("[MORSE] Digit 5: .....")
            dot(pin): dot(pin): dot(pin): dot(pin): dot(pin)
        Case 6 ' -....
            Log("[MORSE] Digit 6: -....")
            dash(pin): dot(pin): dot(pin): dot(pin): dot(pin)
        Case 7 ' --...
            Log("[MORSE] Digit 7: --...")
            dash(pin): dash(pin): dot(pin): dot(pin): dot(pin)
        Case 8 ' ---..
            Log("[MORSE] Digit 8: ---..")
            dash(pin): dash(pin): dash(pin): dot(pin): dot(pin)
        Case 9 ' ----.
            Log("[MORSE] Digit 9: ----.")
            dash(pin): dash(pin): dash(pin): dash(pin): dot(pin)
    End Select
    Log("[MORSE] Digit ", digit, " transmission completed")
End Sub

Sub dot(pin As Byte)
    Log("[MORSE] DOT on GPIO", pin)
    setPinState(pin, True)
    Delay(500) 'Dot - 500ms
    setPinState(pin, False)
    Delay(500) 'Pause between dots/dashes
End Sub

Sub dash(pin As Byte)
    Log("[MORSE] DASH on GPIO", pin)
    setPinState(pin, True)
    Delay(2000) 'Dash - 2000ms
    setPinState(pin, False)
    Delay(500) 'Pause between dots/dashes
End Sub

'Procedure to set port state considering active level
Sub setPinState(pin As Byte, state As Boolean)
    Dim p As Pin
    p.Initialize(pin, p.MODE_OUTPUT)
    If ACTIVE_HIGH Then
        p.DigitalWrite(state)
    Else
        p.DigitalWrite(Not(state))
    End If
End Sub

Hard resetting via RTS pin...
New upload port: COM3 (serial)
=== ESP32-S3 Port Testing Utility ===
Initializing...
Active Level: LOW
Number of test pins: 31
Button pin: GPIO0
Starting in 5 seconds...
Initializing GPIO pins as OUTPUT...
GPIO 1 initialized
GPIO 2 initialized
GPIO 3 initialized
GPIO 4 initialized
GPIO 5 initialized
GPIO 6 initialized
GPIO 7 initialized
GPIO 8 initialized
GPIO 9 initialized
GPIO 10 initialized
GPIO 11 initialized
GPIO 12 initialized
GPIO 13 initialized
GPIO 14 initialized
GPIO 15 initialized
GPIO 16 initialized
GPIO 17 initialized
GPIO 33 initialized
GPIO 34 initialized
GPIO 35 initialized
GPIO 36 initialized
GPIO 37 initialized
GPIO 38 initialized
GPIO 39 initialized
GPIO 40 initialized
GPIO 41 initialized
GPIO 42 initialized
GPIO 45 initialized
GPIO 46 initialized
GPIO 47 initialized
GPIO 48 initialized
Button initialized on GPIO0
=== Starting port testing sequence ===
--- Test Cycle #1 ---
Testing GPIO1 (1/31)
GPIO1 ACTIVATED
GPIO1 DEACTIVATED
Pausing for 2000ms...
GPIO1 test completed
Testing GPIO2 (2/31)
GPIO2 ACTIVATED
GPIO2 DEACTIVATED
Pausing for 2000ms...
GPIO2 test completed
Testing GPIO3 (3/31)
GPIO3 ACTIVATED
GPIO3 DEACTIVATED
Pausing for 2000ms...
GPIO3 test completed
Testing GPIO4 (4/31)
GPIO4 ACTIVATED
GPIO4 DEACTIVATED
Pausing for 2000ms...
GPIO4 test completed
Testing GPIO5 (5/31)
GPIO5 ACTIVATED
GPIO5 DEACTIVATED
Pausing for 2000ms...
GPIO5 test completed
Testing GPIO6 (6/31)
GPIO6 ACTIVATED
GPIO6 DEACTIVATED
Pausing for 2000ms...
GPIO6 test completed
Testing GPIO7 (7/31)
GPIO7 ACTIVATED
GPIO7 DEACTIVATED
Pausing for 2000ms...
GPIO7 test completed
Testing GPIO8 (8/31)
GPIO8 ACTIVATED
GPIO8 DEACTIVATED
Pausing for 2000ms...
GPIO8 test completed
Testing GPIO9 (9/31)
GPIO9 ACTIVATED
GPIO9 DEACTIVATED
Pausing for 2000ms...
GPIO9 test completed
Testing GPIO10 (10/31)
GPIO10 ACTIVATED
GPIO10 DEACTIVATED
Pausing for 2000ms...
GPIO10 test completed
Testing GPIO11 (11/31)
GPIO11 ACTIVATED
GPIO11 DEACTIVATED
Pausing for 2000ms...
GPIO11 test completed
Testing GPIO12 (12/31)
GPIO12 ACTIVATED
GPIO12 DEACTIVATED
Pausing for 2000ms...
GPIO12 test completed
Testing GPIO13 (13/31)
GPIO13 ACTIVATED
GPIO13 DEACTIVATED
Pausing for 2000ms...
GPIO13 test completed
Testing GPIO14 (14/31)
GPIO14 ACTIVATED
GPIO14 DEACTIVATED
Pausing for 2000ms...
GPIO14 test completed
Testing GPIO15 (15/31)
GPIO15 ACTIVATED
GPIO15 DEACTIVATED
Pausing for 2000ms...
GPIO15 test completed
Testing GPIO16 (16/31)
GPIO16 ACTIVATED
GPIO16 DEACTIVATED
Pausing for 2000ms...
GPIO16 test completed
Testing GPIO17 (17/31)
GPIO17 ACTIVATED
GPIO17 DEACTIVATED
Pausing for 2000ms...
GPIO17 test completed
Testing GPIO33 (18/31)
GPIO33 ACTIVATED
GPIO33 DEACTIVATED
Pausing for 2000ms...
GPIO33 test completed
Testing GPIO34 (19/31)
GPIO34 ACTIVATED
GPIO34 DEACTIVATED
Pausing for 2000ms...
GPIO34 test completed
Testing GPIO35 (20/31)
GPIO35 ACTIVATED
GPIO35 DEACTIVATED
Pausing for 2000ms...
GPIO35 test completed
Testing GPIO36 (21/31)
GPIO36 ACTIVATED
GPIO36 DEACTIVATED
Pausing for 2000ms...
GPIO36 test completed
Testing GPIO37 (22/31)
GPIO37 ACTIVATED
GPIO37 DEACTIVATED
Pausing for 2000ms...
GPIO37 test completed
Testing GPIO38 (23/31)
GPIO38 ACTIVATED
GPIO38 DEACTIVATED
Pausing for 2000ms...
GPIO38 test completed
Testing GPIO39 (24/31)
GPIO39 ACTIVATED
GPIO39 DEACTIVATED
Pausing for 2000ms...
GPIO39 test completed
Testing GPIO40 (25/31)
GPIO40 ACTIVATED
GPIO40 DEACTIVATED
Pausing for 2000ms...
GPIO40 test completed
Testing GPIO41 (26/31)
GPIO41 ACTIVATED
GPIO41 DEACTIVATED
Pausing for 2000ms...
GPIO41 test completed
Testing GPIO42 (27/31)
GPIO42 ACTIVATED
GPIO42 DEACTIVATED
Pausing for 2000ms...
GPIO42 test completed
Testing GPIO45 (28/31)
GPIO45 ACTIVATED
GPIO45 DEACTIVATED
Pausing for 2000ms...
GPIO45 test completed
Testing GPIO46 (29/31)
GPIO46 ACTIVATED
GPIO46 DEACTIVATED
Pausing for 2000ms...
GPIO46 test completed
Testing GPIO47 (30/31)
GPIO47 ACTIVATED
GPIO47 DEACTIVATED
Pausing for 2000ms...
[BUTTON] Initial press detected on GPIO47
[BUTTON] CONFIRMED - GPIO47 selected!
[BUTTON] Button pressed: 1
[BUTTON] Selected LED pin: 47
BUTTON PRESSED DETECTED during pause!
=== TESTING INTERRUPTED ===
Selected port: GPIO47
Pausing for 5 seconds before Morse transmission...
=== PORT SELECTED: GPIO47 ===
Starting Morse code transmission...
[MORSE] Transmitting number: 47
[MORSE] Two digits: 4 and 7
[MORSE] Sending digit: 4 on GPIO47
[MORSE] Digit 4: ....-
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DASH on GPIO47
[MORSE] Digit 4 transmission completed
[MORSE] Pause between digits...
[MORSE] Sending digit: 7 on GPIO47
[MORSE] Digit 7: --...
[MORSE] DASH on GPIO47
[MORSE] DASH on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] Digit 7 transmission completed
[MORSE] Transmission completed for number: 47
Morse transmission completed. Pausing for 10 seconds...
=== PORT SELECTED: GPIO47 ===
Starting Morse code transmission...
[MORSE] Transmitting number: 47
[MORSE] Two digits: 4 and 7
[MORSE] Sending digit: 4 on GPIO47
[MORSE] Digit 4: ....-
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DASH on GPIO47
[MORSE] Digit 4 transmission completed
[MORSE] Pause between digits...
[MORSE] Sending digit: 7 on GPIO47
[MORSE] Digit 7: --...
[MORSE] DASH on GPIO47
[MORSE] DASH on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] Digit 7 transmission completed
[MORSE] Transmission completed for number: 47
Morse transmission completed. Pausing for 10 seconds...
=== PORT SELECTED: GPIO47 ===
Starting Morse code transmission...
[MORSE] Transmitting number: 47
[MORSE] Two digits: 4 and 7
[MORSE] Sending digit: 4 on GPIO47
[MORSE] Digit 4: ....-
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DASH on GPIO47
[MORSE] Digit 4 transmission completed
[MORSE] Pause between digits...
[MORSE] Sending digit: 7 on GPIO47
[MORSE] Digit 7: --...
[MORSE] DASH on GPIO47
[MORSE] DASH on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] DOT on GPIO47
[MORSE] Digit 7 transmission completed
[MORSE] Transmission completed for number: 47
Morse transmission completed. Pausing for 10 seconds...
 
Top