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.
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...