This document provides example code and wiring instructions for each peripheral on the 9Mod MCPBoard. All examples are built on the emMCP framework. After registering a tool via emMCP_RegTool, the AI can directly control peripherals or read sensor data through voice commands.
TIP
For the complete project source code, refer to the example/9Mod_MCPBoard/ directory in the emMCP repository.
1. Onboard LED Control
Wiring
The onboard LED is connected to STM32 PC13. Drive high to turn on.
MCP Tool Registration
char* led_control_cb(mcp_server_tool_type_t type, void *param)
{
char *param_str = (char *)param;
cJSON *json = cJSON_Parse(param_str);
cJSON *state = cJSON_GetObjectItem(json, "state");
if (state && strcmp(state->valuestring, "on") == 0) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
}
cJSON_Delete(json);
return "{\"result\": \"ok\"}";
}
emMCP_param_t led_params[] = {
{"state", "Switch state: on/off"}
};
emMCP_tool_t led_tool = {
.name = "led_control",
.description = "Control the onboard LED",
.params = led_params,
.param_count = 1,
.callback = led_control_cb
};
emMCP_RegTool(&emMCP_dev, &led_tool);Voice Commands
"Turn on the LED" "Turn off the LED"
2. Relay Control
Wiring
| Relay Terminal | Description |
|---|---|
| NO (Normally Open) | Open by default, closes when high |
| COM (Common) | Connect to load line |
| GND / VCC | Onboard, no external wiring needed |
STM32 control pin: PB5 (active high).
MCP Tool Registration
// Same pattern as LED control
emMCP_param_t relay_params[] = {
{"state", "Switch state: on/off"}
};
emMCP_tool_t relay_tool = {
.name = "relay_control",
.description = "Control the relay switch",
.params = relay_params,
.param_count = 1,
.callback = relay_control_cb
};
emMCP_RegTool(&emMCP_dev, &relay_tool);Voice Commands
"Turn on the relay" "Turn off the relay"
3. WS2812 LED Strip Control
Wiring
The WS2812 LED strip connects via the onboard 4-pin header:
| WS2812 Pin | Description |
|---|---|
| 5V | Power (onboard 5V output) |
| GND | Ground |
| DIN | Data input — PA11 |
| DOUT | Data output (cascade to next LED) |
Supports RGB color and brightness control.
MCP Tool Registration
emMCP_param_t led_strip_params[] = {
{"red", "Red value 0-255"},
{"green", "Green value 0-255"},
{"blue", "Blue value 0-255"},
{"brightness", "Brightness 0-255"}
};
emMCP_tool_t led_strip_tool = {
.name = "led_control",
.description = "Control WS2812 LED strip color and brightness",
.params = led_strip_params,
.param_count = 4,
.callback = led_strip_cb
};
emMCP_RegTool(&emMCP_dev, &led_strip_tool);Voice Commands
"Set the LED strip to red" "Set brightness to 50%" "Turn off the LED strip"
4. Radar Human Detection
Wiring
The Rd-03L_V2 mmWave radar module connects via a 4-pin header:
| Radar Module | STM32 Pin |
|---|---|
| VCC | 3.3V |
| GND | GND |
| OUT | PA8 (GPIO Input) |
PA8 goes high when human presence is detected, low when empty.
MCP Tool Registration
char* radar_status_cb(mcp_server_tool_type_t type, void *param)
{
uint8_t detected = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8);
char result[64];
snprintf(result, sizeof(result),
"{\"detected\": %s}",
detected ? "true" : "false");
static char ret_buf[64];
strcpy(ret_buf, result);
return ret_buf;
}
emMCP_param_t radar_params[] = {};
emMCP_tool_t radar_tool = {
.name = "get_radar_status",
.description = "Get radar human detection status",
.params = radar_params,
.param_count = 0,
.callback = radar_status_cb
};
emMCP_RegTool(&emMCP_dev, &radar_tool);Voice Commands
"Is anyone in the room?" "Check the radar status"
5. SHT30 Temperature & Humidity
Wiring
SHT30 shares the I²C bus (PB6(SCL) / PB7(SDA)) with the OLED and PD decoy, using separate device addresses:
| Device | I²C Address |
|---|---|
| SHT30 Temp/Humidity | 0x44 |
| OLED SSD1306 | 0x3C |
| CH224K PD Decoy | 0x48 |
MCP Tool Registration
emMCP_param_t env_params[] = {};
emMCP_tool_t env_tool = {
.name = "get_environment",
.description = "Get ambient temperature and humidity",
.params = env_params,
.param_count = 0,
.callback = get_environment_cb
};
emMCP_RegTool(&emMCP_dev, &env_tool);Voice Commands
"What's the temperature and humidity?" "Check the current temperature"
6. IR Air Conditioner Control
Wiring
The HXD039B2 IR transmitter module connects via a 5-pin header:
| IR Module | STM32 Pin |
|---|---|
| VCC | 5V |
| GND | GND |
| TX | PB10 (USART3_TX) |
| RX | PB11 (USART3_RX) |
Baud rate 9600. Built-in IR code library for主流 brands (Gree, Midea).
MCP Tool Registration
emMCP_param_t ir_params[] = {
{"brand", "AC brand: gree/midea"},
{"action", "Action: on/off/temp_up/temp_down"},
{"temperature", "Target temperature: 16-30"}
};
emMCP_tool_t ir_tool = {
.name = "ir_control",
.description = "IR air conditioner control",
.params = ir_params,
.param_count = 3,
.callback = ir_control_cb
};
emMCP_RegTool(&emMCP_dev, &ir_tool);Voice Commands
"Turn on the air conditioner" "Set the AC to 26 degrees" "Turn off the AC"
7. PD Decoy Power Control
Wiring
PD decoy uses a CH224K chip configured via I²C. Connect a PD charger to the Type-C port.
| PD Decoy | STM32 Pin |
|---|---|
| SCL | PB6 |
| SDA | PB7 |
| I²C Address | 0x48 |
MCP Tool Registration
emMCP_param_t pd_params[] = {
{"voltage", "Target voltage: 5/9/12/15/20"}
};
emMCP_tool_t pd_tool = {
.name = "pd_set_voltage",
.description = "Set PD decoy output voltage",
.params = pd_params,
.param_count = 1,
.callback = pd_voltage_cb
};
emMCP_RegTool(&emMCP_dev, &pd_tool);Voice Commands
"Set PD output to 12V" "Boost PD to 20V"
8. OLED Display Control
Wiring
0.96" OLED (SSD1306, 128×64) connects via I²C:
| OLED | STM32 Pin |
|---|---|
| SCL | PB6 |
| SDA | PB7 |
| I²C Address | 0x3C |
Onboard Chinese font chip (GT20L61S) supports Chinese characters, ASCII, and images.
MCP Tool Registration
emMCP_param_t oled_params[] = {
{"text", "Text content to display"}
};
emMCP_tool_t oled_tool = {
.name = "oled_display",
.description = "Display text on the OLED screen",
.params = oled_params,
.param_count = 1,
.callback = oled_display_cb
};
emMCP_RegTool(&emMCP_dev, &oled_tool);Voice Commands
"Display 'Hello' on the OLED" "Show the current temperature on the screen"
9. Full Example: Register All Peripherals
void RegisterAllTools(void)
{
emMCP_RegTool(&emMCP_dev, &led_tool);
emMCP_RegTool(&emMCP_dev, &relay_tool);
emMCP_RegTool(&emMCP_dev, &led_strip_tool);
emMCP_RegTool(&emMCP_dev, &radar_tool);
emMCP_RegTool(&emMCP_dev, &env_tool);
emMCP_RegTool(&emMCP_dev, &ir_tool);
emMCP_RegTool(&emMCP_dev, &pd_tool);
emMCP_RegTool(&emMCP_dev, &oled_tool);
}After registering all tools, call emMCP_RegistrationTools() once to sync all tool definitions to the AI platform.
Verification Method
- Compile check: Ensure the project compiles without errors
- Serial log: After flashing, connect the debug serial port (USART1, 115200). Say "Xiao An" (你好小安) to the module. You should see
[DEBUG] emMCP_EventCallback: event:8log output - Tool sync: When
tool_listtransmission success appears in the serial log, it means the tools have been registered to the AI platform - Functional test: Speak the corresponding voice commands from the examples to observe peripheral responses

