The project miaow-balance-bot is the firmware for a two-wheeled self-balancing robot. This file defines the environment, architecture, coding style, and operational constraints for AI agents working on the MiaoW Balance Bot project.
.
├── CMakeLists.txt # Top-level CMake build entrypoint
├── cmake/ # CMake toolchain files for cross-compilation, generated by STM32CubeMX
│
├── Docs/ # Documentation
│
├── Middlewares/ # Official and third-party middleware directory
│
├── Drivers/ # Driver layer (Silicon vendor peripheral drivers + board-level BSP)
│ ├── CMSIS/ # Cortex-M core support files
│ ├── STM32F1xx_HAL_Driver/ # STM32F1 official HAL library files
│ └── BSP/ # == Custom Board Support Package (BSP) ==
│ ├── Inc/
│ └── Src/
│
└── Core/ # == Application and Core Business Directory ==
├── Inc/
│ /* --- CubeMX Auto-generated Section --- */
│ ├── main.h # Declaration of hardware initialization and main entrypoint
│ ├── ...
│ /* --- Business Subdomain Interface Definitions (Handwritten) --- */
│ ├── app/ # 1. Boot / App Layer (System boot and multi-task orchestrator)
│ ├── platform/ # 2. Platform Layer (Non-business generic system capabilities)
│ ├── services/ # 3. Services Layer (Background shared services)
│ ├── comm/ # 4. Comm Layer (Communication links, protocols, and instruction dispatch)
│ ├── control/ # 5. Control Layer (Core state estimation and control calculation)
│ └── modules/ # 6. Modules Layer (Physical peripheral modules, e.g., OLED/LED displays)
│
└── Src/
/* --- CubeMX Auto-generated Section --- */
├── main.c # Hardware main entrypoint (boots to app_boot after HAL initialization)
├── ...
/* --- Business Subdomain Implementations (Handwritten) --- */
├── app/
├── platform/
├── services/
├── comm/
├── control/
└── modules/
graph TD
app[app]:::moduleStyle
control[control]:::moduleStyle
comm[comm]:::moduleStyle
modules[modules]:::moduleStyle
services[services]:::moduleStyle
platform[platform]:::moduleStyle
app --> platform
app --> control
app --> comm
app --> modules
control --> services
control --> platform
comm --> control
comm --> services
modules --> control
modules --> platform
services --> platform
Refer to Docs/hardware.md for detailed hardware specifications, pin mappings, and peripheral configurations.
- STM32CubeMX 6.18.0
- STM32CubeCLT
Strictly follow the Linux Kernel Code Style, with the following exceptions:
- Use 2 spaces for indentation.
- Recommend the use of
typedeffor structure renaming. - Files in BSP layer must prefixed with
bsp_.
Here is the refined and concise C-language comment style guide tailored to your requirements:
All comments in this project must be written exclusively in English.
Every .c and .h file must start with the SPDX license identifier. Metadata like authors and dates are managed by Git and must not be included in the header.
// SPDX-License-Identifier: MIT
/**
* @file motor_control.c
* @brief Core implementation of twin-wheel balance robot motor PWM calculation.
*/Public APIs in header files require complete documentation. Internal static functions can use simplified inline comments unless they handle complex logic.
@brief: Describe what the function does, not how.@param[in,out]: Specify direction, pointer ownership, and whetherNULLis permitted.@return: Explicitly state the meaning of error codes or special return values.- Side Effects (
@note): Document reentrancy, interrupt-safety (ISR compatibility), and blocking behaviors.
/**
* @brief Calculate PID output for robot upright stabilization.
* @param[in] current_angle Measured tilt angle in degrees.
* @param[in] target_angle Target balance angle in degrees.
* @param[out] output_pwm Pointer to store mapped PWM value. Must not be NULL.
* @return 0 on success, -EINVAL if arguments are out of bounds or pointer is NULL.
* @note Time-sensitive operation. Not thread-safe; do not call concurrently.
*/
int pid_calculate_balance(float current_angle, float target_angle, int16_t *output_pwm);Every member must be explicitly documented, focusing on physical units and constraints.
/**
* @brief Robot attitude telemetry data.
*/
typedef struct {
float pitch; /**< Pitch angle in radians. Range: -pi/2 to pi/2. */
float roll; /**< Roll angle in radians. */
int16_t gyro_z; /**< Raw Z-axis gyroscope ADC reading (unfiltered). */
} robot_attitude_t;Explain the why, not the what. Do not state what the code self-evidently does.
// Clear bits 4:7 and write prescaler value (Prescaler = 4)
TIM1->CR1 &= ~(0xF0);
TIM1->CR1 |= (0x04 << 4); Use standardized labels to mark unfinished or problematic code for easy tracking (grep).
TODO: Unimplemented features or optimizations.FIXME: Known bugs, edge-case vulnerabilities, or temporary workarounds that need refactoring.
// TODO: Implement Kalman filter to replace complementary filter.
// FIXME: Division by zero risk if accelerometer data saturates.- No Commented-Out Code: Never use comments to disable code. Delete it and let Git handle the history, or use
#if 0 ... #endifif conditionally required during debugging. - Consistent Notation: Use Doxygen style
/** ... */for API declarations (files, functions, structs) and standard//for inline logic.
- Simplest working solution. No over-engineering.
- Code First: Return modifications, file creations, or script blocks first.
- Minimal Explanation: Provide explanations after the code block only if the execution logic is non-obvious.
- No Prose: Do not include conversational filler, greetings, or inline commentary.
- Comments: Use code comments sparingly, only where logic is highly ambiguous. Do not generate docstrings or type annotations for unchanged/existing code.
- State the exact bug.
- Show the explicit fix.
- Stop. Do not offer broader architectural suggestions, alternatives, or compliments.
- Never hypothesize or speculate about a bug without reading the relevant source files or logs first.
- Clearly state: What was found, where it was located, and the precise fix in a single pass. If the cause is indeterminate, state it explicitly without guessing.
- Use plain hyphens and straight quotes (' or ") only.
- Do not emit smart quotes, em dashes, or decorative Unicode shapes.
- Atomic Commits: Commit early and often. Create a separate commit for each logical change or calculation step. Do not bundle multiple unrelated structural or content updates into a single monolithic commit.
- Conventional Commits: Every commit message must strictly follow the Conventional Commits specification (e.g.,
feat(contents): add head loss calculation,fix(scripts): resolve division by zero in pipe friction script). - Summarization: The commit message summary line must be highly descriptive and precise, capturing the exact engineering or structural change made.
- Efficient Tooling: Utilize high-performance search utilities such as
ripgrep(rg) andast-grepfor scanning codebase patterns and repository text when gathering context. - Dependency Missing Protocol: If these external search utilities are missing from the system path, immediately pause execution and explicitly prompt the user to install them before attempting any file modifications.
- Additive Bias: Prioritize adding new content, configurations, and scripts. Avoid deleting or overriding existing functional code or prose unless strictly necessary.
- Destructive Change Safeguard: Never silently delete or heavily modify pre-existing logic or text. If code or content appears incorrect, pause and prompt the user for confirmation, allowing them to decide whether to delete or modify it.
- Post-Modification Accountability: After executing any user-approved deletion or modification, explicitly summarize exactly what was changed or removed and state the outcome.
- Strict Boundary Rules: AI agents must never modify any files directly in the root of
Core/Src/orCore/Inc/(such asmain.c,stm32f4xx_it.c, etc.) outside of the explicitly designated/* USER CODE BEGIN */and/* USER CODE END */comment blocks. - Handwritten Logic Isolation: All custom business logic, task setups, and peripheral initializations must be modularized inside the handwritten subdomains (e.g.,
Core/Src/app/,Drivers/BSP/). The entry point insidemain.cmust only contain a single routing call (e.g.,app_boot()) within its user code block to hand over control immediately.
- Unidirectional Dependency Flow: The system architecture must strictly adhere to the unidirectional flow defined in the Mermaid diagram. Reverse dependencies (e.g., a module in
platformincluding a header fromcontrolorapp) are strictly forbidden. - Circular Include Mitigation: To prevent circular dependencies between
comm(which dispatches instructions) andcontrol(which requires state feedback), agents must utilize a *Shared Data Registry- or *Mailbox / Queue- pattern located in theserviceslayer. controltasks must only write state data (e.g., pitch, yaw, encoder speed) to the registry.commtasks must only read from this registry to pack outgoing telemetry frames. Direct API calls fromcontroltocommare strictly prohibited.
-
Zero Dynamic Allocation: Dynamic memory allocation (
malloc,free,pvPortMalloc, etc.) is strictly prohibited within all active run-time tasks, particularly withincontrol/,comm/, andmodules/. All buffers, state structs, and control blocks must be allocated statically or on the stack with deterministic bounds. -
Non-Blocking Control Loop: The core self-balancing control calculation (typically running in a high-priority FreeRTOS task or IMU-triggered ISR at
$200\text{ Hz}$ or higher) must remain strictly non-blocking. - Never call blocking delay functions (such as
vTaskDelayorHAL_Delay) inside the control loop. - All external sensor readings (e.g., MPU6050/ICM20602 via I2C/SPI) and motor outputs must use non-blocking DMA or interrupt-driven transactions. Blocking polling loops (e.g.,
whileloops checking peripheral flags without timeouts) are strictly forbidden.
- Include Paths: All handwritten source files must include headers relative to the
Core/Inc/directory (e.g.,#include "control/control.h"). - No Long Relative Traversals: Agents are strictly forbidden from writing deep relative include paths (such as
#include "../../../control/Inc/control.h"). If a header is not discoverable via standard subfolder relative paths, the build system (CMakeLists.txt) must be updated instead of hardcoding complex paths.
- Hardware-Agnostic Application Layer: The core business modules (
app/,control/) must remain entirely independent of STM32 HAL API calls or registers. Direct register manipulation or calls likeHAL_GPIO_WritePinand__HAL_TIM_SET_COMPAREare strictly forbidden in these layers. - BSP Boundary Control: All hardware actions (e.g., setting motor PWM, reading encoder counts, toggling onboard LEDs) must be encapsulated as clean, abstract function calls provided by the Board Support Package (
Drivers/BSP/). The application layer may only interact with the physical hardware through thesebsp_prefixed functions.