Now that you’ve wired your STM32 Black Pill to an Arduino running JTAGenum and captured output via PuTTY, it’s time to make sense of the data. This part walks you through interpreting FOUND! lines, verifying the detected pins, and locking down a reliable JTAG configuration for future debugging.
Step 9: Understanding the Output Format
JTAGenum tries every possible combination of pins assigned to common JTAG roles: TDI, TDO, TMS, TCK, and nTRST. When a valid combination is found, it prints a line like:
FOUND! ntrst:DIG_4 tck:DIG_6 tms:DIG_7 tdo:DIG_3 tdi:DIG_2 IR length: 34
Here’s what it means:
DIG_x refers to the Arduino digital pin number.
IR length: 34 indicates the Instruction Register (IR) length detected on the JTAG scan chain — and confirms that a valid TAP controller responded.
IR lengths like 4, 5, or 34 are common on STM32 microcontrollers.
Reviewing Real Examples from Your Scan
Let’s break down some actual outputs observed from the Black Pill while in DFU mode:
Detected JTAG Configurations:
Example A:
FOUND! ntrst:DIG_4 tck:DIG_6 tms:DIG_7 tdo:DIG_3 tdi:DIG_2 IR length: 34
Example B:
FOUND! ntrst:DIG_5 tck:DIG_6 tms:DIG_7 tdo:DIG_3 tdi:DIG_2 IR length: 34
Example C:
FOUND! ntrst:DIG_8 tck:DIG_6 tms:DIG_7 tdo:DIG_3 tdi:DIG_2 IR length: 34
All three are valid. The only difference is the nTRST pin. This tells you:
TDI = D2
TDO = D3
TMS = D7
TCK = D6
nTRST = D4 or D5 or D8 — possibly optional or floating
Tip: If you’re only using 4-wire JTAG (TCK, TMS, TDI, TDO), you can ignore nTRST. But including it can improve scan reliability.
Mapping Detected Pins Back to STM32
Let’s assume your earlier connections from Arduino to STM32 were:
Arduino Pin
STM32 Pin
D2
PA15
D3
PB3
D4
PB4
D5
PB13
D6
PB14
D7
PB15
D8
PA12
Then, based on the confirmed working detection:
TDI = PA15
TDO = PB3
TMS = PB15
TCK = PB14
nTRST = PB4 or PB13 or PA12 (D4, D5, or D8)
Result: You’ve successfully mapped the JTAG pins without knowing them in advance — using only multimeter tests, brute-force probing, and observation.
Verifying JTAG Pins with Other Tools (Optional)
To confirm these pin assignments beyond JTAGenum:
Use a debugger like Tigard, J-Link, or ST-Link wired to those pins.
Use OpenOCD with a custom interface config using those exact pins.
Perform a memory read or chip ID query to confirm real access.
Summary: Final Working JTAG Pin Mapping
JTAG Signal
Arduino Pin
STM32 Pin
TDI
D2
PA15
TDO
D3
PB3
nTRST
D4/D5/D8
PB4/PB13/PA12
TCK
D6
PB14
TMS
D7
PB15
This is a stable configuration to use with any JTAG tool or debugger for STM32F411CE.
Final Thoughts
Even if the factory firmware disables JTAG, DFU mode preserves debug pin functionality.
JTAGenum is a powerful tool that lets you discover pinouts with no documentation.
Have you ever wanted to connect sensors to your Raspberry Pi to measure things like temperature, light, or even distance? It sounds complicated with all the wires and circuits, right? Well, there’s a fantastic project called the GrovePi+ Sensor Dashboard that makes it super easy and fun!
This project is like a friendly assistant for your Raspberry Pi. It’s a special program that gives you a simple screen (a “dashboard”) where you can see information from different sensors in real-time. You can also control some devices, like turning a light on or off — all from your computer screen!
Imagine having a mini-laboratory at home. This dashboard helps you:
See Live Data: Watch temperature, humidity, sound, and light levels change in real-time.
Control Things: Turn a relay (like a smart switch) or buzzer (alarm) on and off with a click.
Play with Buttons & Lights: Detect button presses and control small LEDs.
Measure Distance: Use an ultrasonic sensor to measure how far things are.
Check the Weather: Get real-time environmental updates.
It’s all displayed in a clear, easy-to-use window on your Raspberry Pi. This makes it perfect if you’re just starting with electronics, learning about the Internet of Things (IoT), or trying out Python programming.
Why Is It So Easy?
The secret is the GrovePi+ board. It plugs into your Raspberry Pi, and sensors connect with special cables — no messy wiring or soldering. You spend less time troubleshooting and more time building your ideas.
What You Need to Get Started
Raspberry Pi 3B or 4B
GrovePi+ board by Seeedstudio
MicroSD card (with Raspberry Pi OS Buster or Stretch)
Power supply
Grove sensors (e.g., DHT11, button, relay, ultrasonic ranger)
The dashboard relies on a few key Python libraries to function:
sudo apt-get install python3-pyqt5 (PyQt5): This is the core toolkit that builds the graphical user interface (GUI) of your dashboard. Without PyQt5, the application wouldn’t have its visual windows, buttons, or sensor displays.
pip3 install pandas (Pandas): This powerful library is used for managing and analyzing data. In your dashboard, it helps organize the historical sensor readings, especially for displaying them in clear graphs.
pip3 install pyqtgraph (PyQtGraph): Built on top of PyQt5, PyQtGraph is dedicated to creating dynamic and interactive data plots. It’s what allows the dashboard to show you beautiful graphs of your sensor data over time.
How the Dashboard Works: A Deep Dive into the Code Architecture
The GrovePi+ Sensor Dashboard is built with a well-organized and modular design, using several Python files that work together seamlessly. This structure makes the project robust, easy to understand, and simple to expand.
1. Core Application Orchestration:
main_window.py: This is the central control hub of the entire application.
Initialization: It kicks off essential background services like the ConfigManager (for settings), Logger (for recording events), and StorageMonitor (for checking disk space).
Tab Management: It’s responsible for setting up the main window’s tabbed interface, creating each of the specific UI tabs (like Dashboard, Weather, Settings, etc.), and adding them to the window.
Background Processing: Crucially, it starts a separate SensorWorker thread. This is vital because reading sensor data can sometimes take time or involve waiting, and putting this work in a separate thread prevents the main application screen from freezing, keeping the user interface smooth and responsive.
Communication Hub: It acts as the primary connector, linking signals (messages) from the SensorWorker (with new sensor data) and the GrovePiSensorManager (with control feedback) to the right “slots” (update functions) in the various UI tabs, ensuring all displays update in real-time.
System Status & Theming: It also handles periodic checks on system health and manages the application-wide theme, making sure all parts of the UI look consistent with your chosen colors.
2. Hardware Interaction & Sensor Management:
grovepi_sensor_manager.py: This module is your hardware communication expert.
Abstraction: It hides the complex details of talking directly to the GrovePi+ board and its sensors. Instead, other parts of the program can ask it for sensor data or tell it to control devices using simple commands.
Data Collection: Contains specialized functions to read information from each type of connected Grove sensor, whether they are digital (like a button) or analog (like a light sensor).
Device Control: Provides methods to send commands to output devices, such as turning a relay on/off or setting the brightness level of an LED bar.
Mock Mode: A super helpful feature! It has a “mock mode” which simulates sensor readings and device responses without needing the actual physical GrovePi+ board or sensors. This is fantastic for developing and testing the software on any computer.
Feedback Signals: It sends out notifications (PyQt signals) when a device’s state changes (e.g., when the relay turns on), allowing the dashboard to update its display immediately.
3. User Interface (UI) Modules (The Dashboard Screens):
The application’s interface is divided into several dedicated Python files, each creating a specific PyQt5 QWidget (a screen or “tab”) within the main window. This keeps the interface organized and easy to build upon.
dashboard_tab.py: Your main overview screen. It displays a quick, at-a-glance summary of the most important sensor readings and even integrates current weather information. It uses compact visual gauges to show data clearly.
environment_sensors_tab.py: Focuses on environmental readings, providing a more detailed view of temperature and humidity using dedicated gauges.
basic_analog_sensors_tab.py: Shows data from your analog sensors, such as values from sound, light, and rotary angle sensors, often using different visual styles for their displays.
interactive_control_sensors_tab.py: This is where you actively control and interact with devices. You can see the status of buttons, toggle relays, control the LED bar’s brightness, and monitor the rotary angle sensor.
plots_tab.py: The data analysis center. This tab lets you see historical sensor data in interactive graphs using powerful pandas and pyqtgraph libraries. You can select which sensors to plot and choose different time periods to see trends, and even export the graphs!
settings_tab.py: Your dashboard’s control panel. Here, you can customize how the application works. This includes enabling/disabling logging, setting up where data and logs are saved, entering your OpenWeatherMap API key for weather data, and even switching between mock (simulated) or live (real) sensor modes. It also shows you the available storage space on your Raspberry Pi.
ui_customization_tab.py: Allows you to personalize the look and feel of your dashboard. You can choose from different color themes to match your preference.
4. Custom UI Widgets (The “Mini-Artists”):
These modules define specialized, visually appealing PyQt5 QWidgets that draw unique components like gauges and LED bars, making the data more engaging.
gauge_widget.py, gui_widgetsone.py, gui_widgets_multiring.py: These files contain the code for drawing various circular gauge displays. They take raw sensor numbers and visually represent them with needles, arcs, and colors. Some can even change color (e.g., to orange or red) if a sensor reading goes into a “warning” or “critical” range.
led_bar_widget.py: This creates a custom visual LED bar on the screen, showing how many of its 10 segments are lit based on a numerical value. The colors of the lit segments (green, yellow, red) provide an immediate visual cue of the level.
dashboard_gauge_widget.py: A compact gauge designed specifically for the dashboard overview. It’s smaller but still effectively displays sensor values with a circular progress indicator and color-coded alerts.
5. Utility Modules (Behind-the-Scenes Helpers):
These are crucial support modules that handle common tasks across the application.
config_manager.py: The memory of the application. This clever module ensures that all your settings (like your chosen theme, API keys, or log folders) are saved to a file (app_config.json) and remembered the next time you open the dashboard. It uses a “singleton” pattern, meaning there’s only ever one copy of your settings available to the whole program, preventing confusion.
logger.py: The application’s diary. This module records important messages, warnings, and errors as the program runs, both to your computer screen and to special log files. This is incredibly helpful for figuring out what went wrong if something unexpected happens. It also manages log file sizes, so they don’t fill up your disk.
storage_monitor.py: Your disk space checker. This utility helps the dashboard keep an eye on how much free space is left on your Raspberry Pi. It’s especially useful for making sure there’s enough room for all the sensor data and log files.
weather_api.py: The weather reporter. This module connects to an online weather service (OpenWeatherMap) to fetch live weather information for your chosen location, displaying it directly on your dashboard. It smartly gets your API key and city details from the config_manager.
All these components, from the central window to the smallest utility, work in harmony. This makes the GrovePi+ Sensor Dashboard a powerful, extensible, and user-friendly solution for all your Raspberry Pi sensor projects!
See It in Action!
Dashboard Overview
Dashboard
Environment Sensors Tab
Environment Sensors
Analog Sensors Tab
Basic Analog Sensors
Interactive Sensors Tab
Interactive Sensors
Weather Tabs
Current Weather24 Hours Weather Forecast5 Day Weather Forecast
Important Safety Note
This project is for educational and prototyping use. Always handle electronics with care, especially when using powered modules like relays. Use responsibly and follow safety instructions.
Credits and Liability Disclaimer
This code for the GrovePi+ Sensor Dashboard has been generated using Gemini, an AI large language model, with direct input and feedback from gr4ytips.
The information, software, and associated documentation are provided “as is” without warranty of any kind, either express or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
Now it’s time to automate discovery. We’ll use a tool called JTAGenum, which runs on an Arduino and probes the target’s pins to discover JTAG lines.
In this step, you’ll set up an Arduino board with the JTAGenum firmware and wire it to the STM32. This allows you to scan multiple GPIO pins and automatically detect which ones are connected to JTAG signals like TCK, TMS, TDI, TDO, and nTRST. Before running running JTAGenum, put the Black Pill into DFU mode.
Choosing the Right Arduino Board
To run JTAGenum, you’ll need an Arduino board with:
Stable USB-to-serial interface for live interaction
Comparison of Popular Arduino Boards:
Board
Logic Level
Suitability for STM32
Notes
Nano
5V
⚠️ Needs level shifter
Small, easy to set up, but risky directly
Uno
5V
⚠️ Needs level shifter
Easy to flash, but needs care
Due
3.3V
Perfect match
Many pins, safe for STM32
Recommendation: Use an Arduino Due. It runs at 3.3V logic, which is electrically safe for direct connection to STM32F4 GPIOs, and has plenty of pins for full JTAG probing.
Connecting the Black Pill to Arduino (Any Order)
Candidate Pins on STM32 (Black Pill)
You likely do not have access to PA13 or PA14, the standard TMS/TCK lines — but you can still discover alternate JTAG mappings using brute-force scanning.
Use any 7 to 10 of these available pins on the Black Pill:
PA15
PB15
PB14
PB13
PB12
PB10
PA12
PA11
PA10
PA9
Example Wiring: STM32 ↔ Arduino Due
You can connect any STM32 pins to any Arduino pins D2–D11, in no particular order — JTAGenum will test all combinations.
STM32 Pin
Arduino Due Pin
PA15
D2
PB15
D3
PB14
D4
PB13
D5
PB12
D6
PB10
D7
PA12
D8
PA11
D9
PA10
D10
PA9
D11
GND
GND
Note: Only connect GND↔GND and signal pins, avoid VCC/3.3V unless you’re powering the STM32 from Arduino.
(Optional) Enable Always overwrite it to avoid appending old logs
Return to Session and click Open
Starting the Scan
The PuTTY terminal should open.
Press s (lowercase) to start scanning.
You’ll see output like:
FOUND! ntrst:DIG_4 tck:DIG_6 tms:DIG_7 tdo:DIG_3 tdi:DIG_2 IR length: 34
This means:
TDI = D2 = PA15
TDO = D3 = PB3
TCK = D6 = PB14
TMS = D7 = PB15
nTRST = D4 = PB4 (optional)
IR length: 34 is expected for STM32F4 devices — this confirms that the JTAG chain was successfully detected!
Tip: JTAGenum brute-forces all combinations — so don’t worry about wiring order. It figures it out.
Tip for Analysis: Watch for lines with FOUND! and IR length > 0 — that’s a confirmed JTAG match.
Safety Precautions
When working with electronics, especially when connecting different devices, safety is paramount to prevent damage to your hardware. Here are a couple of crucial precautions to keep in mind:
Establish a Common Ground
It’s critically important to ensure a common ground connection between your Arduino Due and the target STM32 device. Think of ground as the zero-voltage reference point in your circuit. If the two devices don’t share the same ground, they won’t have a consistent reference for their voltage signals. This can lead to erratic behavior, incorrect readings, or even permanent damage to one or both devices as current tries to find an alternate, potentially damaging, path. Always connect the GND pin of your Arduino to a GND pin on your STM32 before making any other connections.
Consider Current-Limiting Resistors
While the Arduino Due’s 3.3V logic is generally safe for STM32 GPIOs, it’s a good practice to briefly consider the benefits of using current-limiting resistors on your probing lines, particularly when working with unknown or potentially sensitive pins. A small resistor (e.g., 100-470 ohms) in series with your data lines can act as a fuse, limiting the current if an accidental short circuit or a voltage mismatch occurs. This extra layer of protection can significantly reduce the risk of damage to your microcontroller’s delicate input/output pins, especially during initial exploration or troubleshooting.
Troubleshooting Tips
Even with careful setup, you might encounter issues when trying to automatically detect JTAG pins. This section covers some common problems and provides guidance on how to troubleshoot them.
1. Incorrect Wiring
Symptom: No detection, inconsistent results, or unexpected behavior.
Solution: The most frequent cause of problems is incorrect wiring.
Double-check every connection: Carefully review your wiring diagram and compare it against your physical setup. Ensure that each pin from the Arduino Due is connected to the correct corresponding pin on the STM32 (e.g., TCK to TCK, TMS to TMS, etc.).
Verify common ground: Confirm that the ground (GND) of your Arduino Due is securely connected to a ground pin on your STM32. A missing or poor ground connection is a common culprit for communication failures.
Check for loose connections: Ensure all wires are firmly seated in their respective headers or breadboard points.
2. Serial Communication Problems
Symptom: No output in the serial terminal (PuTTY), garbled text, or connection errors.
Solution: Issues with the serial connection between your computer and the Arduino Due can prevent you from interacting with JTAGenum or seeing its output.
Verify COM Port: Make sure you have selected the correct COM port for your Arduino Due in PuTTY (or your chosen serial terminal). You can usually find this in your computer’s Device Manager.
Check Baud Rate: Ensure that the baud rate in your serial terminal matches the baud rate configured in the JTAGenum firmware (commonly 115200).
Install Drivers: Confirm that the necessary USB serial drivers for your Arduino Due are correctly installed on your computer.
Close other serial monitors: Ensure no other applications (like the Arduino IDE’s Serial Monitor) are currently using the same COM port.
3. False Positives or Inconclusive Results
Symptom: JTAGenum reports pins that don’t seem to be JTAG, or the scan doesn’t identify all expected pins.
Solution: This can sometimes happen due to electrical noise or unexpected pin states.
Re-run the scan: Sometimes, simply re-running the JTAGenum scan multiple times can help confirm results or reveal inconsistencies.
Minimize environmental noise: Try to reduce electrical noise in your workspace. This might involve moving away from power supplies, motors, or other noisy electronics.
Isolate the target: If possible, disconnect other peripherals from the STM32 during the scan to ensure only the JTAGenum is influencing the pins.
4. Cross-Talk
Symptom: Intermittent errors, unexpected data on seemingly unrelated pins, or difficulty in getting stable results.
Solution: Cross-talk occurs when signals on one wire induce unwanted signals on adjacent wires. This is more common with long, unshielded wires or when many wires are bundled closely together.
Shorten wires: Use the shortest possible wires for your connections.
Separate sensitive lines: Try to keep the JTAG data lines (TDI, TDO, TMS, TCK) physically separated from each other and from other noisy signals as much as possible.
Twisted pairs: For very sensitive applications, using twisted pair wires (though less common for simple JTAG probing) can help reduce cross-talk.
End of Part 2
Coming up in Part 3:
How to interpret JTAGenum logs
How to confirm real JTAG mappings
Final working pin configurations for the Black Pill