2025-10-31 19:52:24 +01:00
2025-10-30 14:45:28 +01:00
2025-10-31 19:52:24 +01:00
2025-10-30 14:45:28 +01:00

SSD1306 OLED Servo Control with STM32 Blue Pill

This project demonstrates how to control a servo motor using an IBT_2 (BTS7960) motor driver, an STM32 Blue Pill, and a 128x64 SSD1306 OLED display. The user can control the motor's speed and direction using four push buttons, with real-time feedback on the OLED screen. It shows how to use the DAPLink programmer in Arduino IDE v2 with debugging.

Features

  • Motor Control: Adjust speed and direction of a servo motor.
  • OLED Display: A 128x64 SSD1306 OLED display shows the current speed, direction, and motor state (ON/OFF).
  • User Interface: A simple and intuitive interface with four buttons for control (Up, Down, OK, Cancel).
  • Two-Color Display Optimization: The UI is designed for two-color (Yellow and Blue) OLED displays, with a static header in the yellow section and dynamic values in the blue section.

Hardware Required

  • STM32F103C8T6 "Blue Pill" development board
  • 128x64 SSD1306 OLED display (I2C) with 4 push buttons (up, down, OK, Back)
  • IBT_2 (dual BTS7960) motor driver
  • Servo motor e.g.: RS-550 or R-775
  • External power supply for the motor 12-24V/5A
  • Breadboard and jumper wires

Wiring

Connect the components to the Blue Pill as described below.

OLED Display (I2C)

OLED Display Pin Blue Pill Pin
VCC 3.3V
GND GND
SCL PB6
SDA PB7

Control Buttons

The buttons are connected to GPIO pins using the internal pull-up resistors. The other terminal of each button should be connected to GND.

Button Function Blue Pill Pin
Up PA0
Down PA1
OK PA2
Cancel PA3

IBT_2 Motor Driver

The IBT_2 module requires its own power supply for the motor.

IBT_2 Pin Blue Pill Pin Description
VCC 5V Logic Power
GND GND Logic Ground
R_EN 3.3V Right Enable (connect to 3.3V)
L_EN 3.3V Left Enable (connect to 3.3V)
RPWM PB0 Right PWM Signal (Forward)
LPWM PB1 Left PWM Signal (Reverse)

For debugging and logging, you can connect the DAPLink's virtual COM port to the Blue Pill's UART1.

DAPLink Pin Blue Pill Pin Description
RXD PA9 (TX1) Connect to TX
TXD PA10 (RX1) Connect to RX
GND GND Common Ground

IBT_2 Power Connections:

IBT_2 Terminal Connection
B+ Positive of Motor Power Supply
B- Negative of Motor Power Supply
M+ Positive of Servo Motor
M- Negative of Servo Motor

Dependencies

This sketch requires the following Arduino libraries:

  • Wire
  • Adafruit_GFX
  • Adafruit_SSD1306
  • Adafruit_BusIO (A dependency for the Adafruit libraries)

Getting Started

Prerequisites

Installation

  1. Install arduino-cli: Follow the official instructions at arduino.github.io/arduino-cli/installation/.

  2. Initialize and Configure arduino-cli:

    • Create a default configuration file:
      arduino-cli config init
      
    • Add the STMicroelectronics board manager URL:
      arduino-cli config add board_manager.additional_urls https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json
      
    • Update the local core index:
      arduino-cli core update-index
      
    • Install the STM32 core:
      arduino-cli core install STMicroelectronics:stm32
      
  3. Install Required Libraries:

    arduino-cli lib install "Adafruit SSD1306" "Adafruit GFX Library" "Adafruit BusIO"
    

Board Setup

In Arduino IDE → Tools, set:

Board → STM32 MCU based boards → Generic STM32F1 series

Board part number → BluePill F103CB (or C8 with 128K)

Upload Method → OpenOCD DAPLink (SWD)

Compilation

  1. Prepare Your Sketch Directory: Ensure your sketch file is named SSD1306_sketch.ino and is located in a folder with the same name. For example: /path/to/your/project/SSD1306_sketch/SSD1306_sketch.ino

  2. Compile the Sketch: Compile the sketch for the Blue Pill (STM32F103CB or C8 with 128k), specifying the OpenOCD upload method.

    arduino-cli compile --fqbn STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103CB,upload_method=OpenOCDDapLink /path/to/your/project/SSD1306_sketch
    

    The binary files will be generated in a temporary build directory. To find the path to the binary, you can run the compile command with the --verbose flag.

Upload to the Board

The compiled sketch can be uploaded to the Blue Pill using openocd. The exact command may vary depending on your setup.

First, you need to find the path to your compiled .elf file. You can find this in the output of the arduino-cli compile command. It will be in a temporary directory ~/.cache/arduino/sketches.

Then, find the openocd e.g.: ~/.arduino15/packages/STMicroelectronics/tools/xpack-openocd/0.12.0-6/bin/openocd or install a distro specific version e.g.: sudo apt install openocd. Example of the path to the compiled sketch: /home/martin/.cache/arduino/sketches/96DBB1C909C240C2F96DCDD5DDFB9A12/SSD1306_sketch.ino.elf

Here is an example command to upload the sketch using DAPLink:

/path/to/your/openocd -d2 -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg -c "program {/path/to/your/sketch.ino.elf} verify reset exit"

This section describes how to enable hardware debugging for the STM32F103 "Blue Pill" board using a DAPLink / CMSIS-DAP debugger in Arduino IDE 2.
By default, the STM32 Arduino core loads the wrong OpenOCD configuration (dapdirect_swd, meant for ST-Link).

Until the issues/2807 is not fixed, follow these steps to work around it:

🧭 1. Locate STM32 Core Folder (Linux)

Open a terminal and navigate to your STM32 Arduino core installation:

cd ~/.arduino15/packages/STMicroelectronics/hardware/stm32/2.11.0/

Adjust the version number if different (check in Arduino IDE → Tools → Board → Boards Manager).

🧰 2. Create or Edit platform.local.txt

Create (or edit) a local override file:

nano platform.local.txt

Paste the following lines:

debug.server.openocd.scripts.0=interface/cmsis-dap.cfg
debug.server.openocd.scripts.1={runtime.platform.path}/debugger/select_swd.cfg

Save and close (Ctrl + O, Enter, Ctrl + X).

These lines tell OpenOCD to:

  • Use the CMSIS-DAP interface interface/cmsis-dap.cfg

  • Use standard SWD transport select_swd.cfg instead of dapdirect_swd

🔁 3. Restart Arduino IDE

Completely close and reopen Arduino IDE 2 to apply the new settings.

⚙️ 4. Configure the IDE

In Arduino IDE → Tools, set:

  • Debug symbols and core logs → Core Logs and Symbols Enabled (-g)

  • Optimize → Debug (-Og)

Then click the 🐞 Debug icon and press Start Debugging.

Troubleshooting

1. Cannot Re-program Blue Pill After First Flash

This guide addresses an issue where a Blue Pill (STM32F103) board can be programmed successfully once with Embeetle, but all subsequent attempts fail with an error similar to Error: Error connecting DP: cannot read IDR.

Symptom: The OpenOCD output shows the following error on the second flash attempt:

Error: Error connecting DP: cannot read IDR
in procedure 'program'
** OpenOCD init failed **

The Cause

The root cause is that the application code reconfigures the debug pins (PA13 for SWDIO and PA14 for SWCLK) for other purposes. This effectively disables the Serial Wire Debug (SWD) interface, preventing the DAPLink programmer from establishing a connection.

The SWD interface can be activated manually by switching the BOOT0 jumper to 1 and the pressing reset button. However, this is inconvenient for normal development workflows.

The Solution

Change the configuration to keep the SWD interface enabled.

  1. Open the file stm32f1xx_hal_msp.c in your project. It is usually located in the Src or Core/Src directory.
  2. Locate the HAL_MspInit() function.
  3. Inside this function, find the line that disables the debug interface. It typically looks like this:
    /**DISABLE: JTAG-DP Disabled and SW-DP Disabled
    */
    __HAL_AFIO_REMAP_SWJ_DISABLE();
    
  4. Replace it with the following line to keep SWD enabled while disabling the less-common JTAG interface:
    /** DISABLE: JTAG-DP Disabled but keep SW-DP Enabled
    */
    __HAL_AFIO_REMAP_SWJ_NOJTAG();
    

2. Error: Unable to reset target

If you encounter the following error message in Embeetle's output console during a flashing attempt:

Error: timed out while waiting for target halted
embedded:startup.tcl:1813: Error: ** Unable to reset target **
in procedure 'program'

This typically means there is a mismatch between the reset strategy configured in OpenOCD and your physical wiring. By default, the project is configured to use a hardware reset, which requires the nRST pin to be connected.

The most reliable solution is to ensure your wiring matches the default configuration.

Make sure the nRST pin of your DAPLink programmer is connected to the R (Reset) pin on the Blue Pill's board.

Your connections should be:

  • VCC -> 3.3V
  • SWDIO -> DIO
  • SWCLK -> CLK
  • GND -> G
  • nRST -> R

Solution 2 (Alternative): Use a Software Reset

If you prefer to use a 3-wire setup (SWDIO, SWCLK, GND) and not connect the reset pin, you must change the configuration to instruct OpenOCD to use software-based reset commands instead of toggling a physical pin.

  1. Open the project file ../config/openocd_chip.cfg.
  2. Find the following line:
    reset_config srst_only
    
  3. Change it to none:
    reset_config none
    
  4. Save the file and try programming again.
Description
Programming of the STM32F103CB (BluePill) with an i2c display, buttons and PWM for a motor using DAPLink programmer in Arduino IDE v2 with debugging.
Readme 35 KiB
Languages
C++ 100%