Sensor Device BOM Design
Check and clean dangling traces before routing
Run auto-route
Run DRC focused on airwires and clearance after routing
Summarize routing DRC issues and next fixes
On it...
Table
| Function | MCU Pin | Net | Connected To | Direction | Notes |
|---|---|---|---|---|---|
| I2C SCL | PB6 | I2C_SCL | BME280, BME688, LIS2DW12, TSL25911, SCD41, camera placeholder | AF OD | 4.7 kΩ pull-up to 3V3. |
| I2C SDA | PB7 | I2C_SDA | BME280, BME688, LIS2DW12, TSL25911, SCD41, camera placeholder | AF OD | 4.7 kΩ pull-up to 3V3. |
| SPI SCK | PA5 | SPI_SCK | BGT60TR13C, camera placeholder | AF push-pull | Keep short in layout. |
| SPI MISO | PA6 | SPI_MISO | BGT60TR13C, camera placeholder | Input AF | Shared SPI data in. |
| SPI MOSI | PA7 | SPI_MOSI | BGT60TR13C, camera placeholder | AF push-pull | Shared SPI data out. |
| Radar CS | PB0 | RADAR_CS | BGT60TR13C CS_N | GPIO out | Active low, pulled up. |
| Radar IRQ | PB1 | RADAR_IRQ | BGT60TR13C IRQ | GPIO interrupt | Rising/falling edge per driver. |
| Radar reset | PB2 | RADAR_RESET | BGT60TR13C DIO3/reset | GPIO out | Pulse per Infineon driver requirements. |
| PM UART TX | PA2 | UART_TX_MCU | PMS5003 RX, debug J2 | UART TX | 9600 8N1 for PMS5003. |
| PM UART RX | PA3 | UART_RX_MCU | PMS5003 TX, debug J2 | UART RX | 9600 8N1 for PMS5003. |
| PDM clock | PB13 | PDM_CLK | IM69D130 clock | PDM clock | Configure SAI/DFSDM/PDM peripheral as supported by STM32WBA. |
| PDM data | PB14 | PDM_DATA | IM69D130 data | PDM data in | Mono microphone. |
| IR PWM | PA4 | IR_PWM | AO3400A gate through R25 | Timer PWM | Drives four SFH 4045N IR LEDs through MOSFET. |
| Light interrupt | PC13 | LIGHT_INT | TSL25911 INT | GPIO interrupt | Pull-up to 3V3. |
| Accelerometer INT1 | PB8 | ACCEL_INT1 | LIS2DW12 INT1 | GPIO interrupt | Wake/tamper interrupt. |
| Accelerometer INT2 | PB9 | ACCEL_INT2 | LIS2DW12 INT2 | GPIO interrupt | Optional secondary interrupt. |
| NH3 ADC | PA0 | NH3_ADC | MiCS-6814 NH3 divider | ADC input | Requires calibration. |
| RED gas ADC | PA1 | RED_GAS_ADC | MiCS-6814 RED divider | ADC input | Requires calibration. |
| OX gas ADC | PA11 | OX_GAS_ADC | MiCS-6814 OX divider | ADC input | Requires calibration. |
| Camera reset | PB3 | CAM_RESET | J1 camera placeholder | GPIO out | Placeholder until exact VD55G4 module is defined. |
| Camera sync | PA15 | CAM_FRAME_SYNC | J1 camera placeholder | GPIO in/out | Placeholder frame/strobe sync. |
| SWDIO | PA13 | SWDIO | J2 | Debug | SWD. |
| SWCLK | PA14 | SWCLK | J2 | Debug | SWD. |
| Reset | NRST | NRST | J2 and pull-up | Reset | Active low. |
| Boot mode | PH3_BOOT0 | BOOT0 | 10 kΩ pulldown | Boot strap | Low = normal boot. |
| USB debug UART TX | PA9 | DBG_UART_TX_MCU | CP2102N RXD | UART TX | Dedicated USB-C debug console path. |
| USB debug UART RX | PA10 | DBG_UART_RX_MCU | CP2102N TXD | UART RX | Dedicated USB-C debug console path. |
| Status LED | PA8 | STATUS_LED | R32 + LED2 | GPIO output | User firmware status indicator. |
C
#include "main.h" #include <string.h> #include <stdio.h> I2C_HandleTypeDef hi2c1; SPI_HandleTypeDef hspi1; UART_HandleTypeDef huart2; UART_HandleTypeDef huart1; ADC_HandleTypeDef hadc1; TIM_HandleTypeDef htim2; #define RADAR_CS_GPIO_Port GPIOB #define RADAR_CS_Pin GPIO_PIN_0 #define RADAR_RESET_GPIO_Port GPIOB #define RADAR_RESET_Pin GPIO_PIN_2 #define CAM_RESET_GPIO_Port GPIOB #define CAM_RESET_Pin GPIO_PIN_3 #define IR_PWM_TIMER htim2 #define IR_PWM_CHANNEL TIM_CHANNEL_1 #define STATUS_LED_GPIO_Port GPIOA #define STATUS_LED_Pin GPIO_PIN_8 #define BME280_ADDR (0x76 << 1) #define BME688_ADDR (0x77 << 1) #define TSL2591_ADDR (0x29 << 1) static void Error_Handler_User(const char *msg) { HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); HAL_UART_Transmit(&huart2, (uint8_t*)"\r\n", 2, HAL_MAX_DELAY); } static uint8_t i2c_read_u8(uint16_t addr, uint8_t reg) { uint8_t value = 0; HAL_I2C_Mem_Read(&hi2c1, addr, reg, I2C_MEMADD_SIZE_8BIT, &value, 1, 100); return value; } static void i2c_write_u8(uint16_t addr, uint8_t reg, uint8_t value) { HAL_I2C_Mem_Write(&hi2c1, addr, reg, I2C_MEMADD_SIZE_8BIT, &value, 1, 100); } static void init_environment_sensors(void) { uint8_t id_bme280 = i2c_read_u8(BME280_ADDR, 0xD0); uint8_t id_bme688 = i2c_read_u8(BME688_ADDR, 0xD0); char msg[64]; snprintf(msg, sizeof(msg), "BME280 ID=0x%02X BME688 ID=0x%02X", id_bme280, id_bme688); Error_Handler_User(msg); /* Basic forced-mode examples; replace with Bosch/Sensirion/ST production drivers. */ i2c_write_u8(BME280_ADDR, 0xF4, 0x25); i2c_write_u8(BME688_ADDR, 0xF4, 0x25); } static void init_radar(void) { HAL_GPIO_WritePin(RADAR_CS_GPIO_Port, RADAR_CS_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(RADAR_RESET_GPIO_Port, RADAR_RESET_Pin, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(RADAR_RESET_GPIO_Port, RADAR_RESET_Pin, GPIO_PIN_SET); HAL_Delay(50); } static void read_pms5003_frame(void) { uint8_t frame[32]; if (HAL_UART_Receive(&huart2, frame, sizeof(frame), 1000) == HAL_OK) { if (frame[0] == 0x42 && frame[1] == 0x4D) { uint16_t pm25 = ((uint16_t)frame[12] << 8) | frame[13]; char msg[64]; snprintf(msg, sizeof(msg), "PM2.5=%u ug/m3", pm25); Error_Handler_User(msg); } } } static uint32_t read_adc_channel(uint32_t channel) { ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = channel; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; HAL_ADC_ConfigChannel(&hadc1, &sConfig); HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 100); uint32_t value = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); return value; } static void set_ir_strobe_duty(uint16_t duty) { __HAL_TIM_SET_COMPARE(&IR_PWM_TIMER, IR_PWM_CHANNEL, duty); } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_I2C1_Init(); MX_SPI1_Init(); MX_USART2_UART_Init(); MX_USART1_UART_Init(); MX_ADC1_Init(); MX_TIM2_Init(); HAL_TIM_PWM_Start(&IR_PWM_TIMER, IR_PWM_CHANNEL); set_ir_strobe_duty(0); Error_Handler_User("STM32WBA sensor node boot"); HAL_GPIO_WritePin(STATUS_LED_GPIO_Port, STATUS_LED_Pin, GPIO_PIN_SET); init_environment_sensors(); init_radar(); while (1) { read_pms5003_frame(); uint32_t nh3 = read_adc_channel(ADC_CHANNEL_0); /* PA0 */ uint32_t red = read_adc_channel(ADC_CHANNEL_1); /* PA1 */ uint32_t ox = read_adc_channel(ADC_CHANNEL_15); /* PA11 on many STM32 variants; verify CubeMX mapping */ char msg[96]; snprintf(msg, sizeof(msg), "ADC NH3=%lu RED=%lu OX=%lu", nh3, red, ox); Error_Handler_User(msg); HAL_Delay(5000); HAL_GPIO_TogglePin(STATUS_LED_GPIO_Port, STATUS_LED_Pin); } }
Platform & Toolchain
Pin Mapping From Schematic
I2C Device Address Plan
Bring-Up Sequence
STM32Cube Configuration Checklist
Minimal HAL Skeleton
Build & Flash
Notes Before Production Firmware