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

 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…