yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
MSPM0 Smart Robot Car📖
1.Quick Start Guide
  • 1. Assembly Videos
  • 2. Quick Start Videos
  • 3. Battery charging
  • 4. Notes
2.Introduction to the MSPM0 Car
  • 1.About MSPM0
  • 2.Development board interface description
3.Development environment setup and usage
  • 1.CCS Theia development
  • 2.MDK Arm development
  • 3.Uniflash burning
  • 4.External crystal oscillator configuration
  • 5.Project Migration
4.MSPM0 basic course
  • 1. LED light control (GPIO)
  • 2. Buzzer Control (GPIO)
  • 3. Button Control (EXTI)
  • 4. Serial Port (UART)
  • 5. Voltage Detection (ADC)
  • 6. Temperature Detection (ADC)
  • 7. Independent Watchdog (WWDG)
  • 8. Window Watchdog (WWDG)
  • 9. Timer (TIM)
  • 10. Breathing LED (PWM)
  • 11. I2C Communication (I2C)
  • 12. External Flash (SPI)
  • 13. Internal Flash (Flash)
  • 14. DMA
  • 15. FreeRTOS
5.Sensor basic course
  • 1.Servo control
  • 2.Ultrasonic servo PTZ basic use
  • 3.Motor PID control
  • 4.OLED display photosensitive value
  • 5.Infrared avoid sensor
  • 6.1 Infrared line tracking sensor-8 channel infrared tracking sensor module
  • 6.2 Infrared line tracking sensor-4 channel infrared tracking sensor module
  • 7.Infrared remote control
  • 8.Ultrasonic ranging
  • 9.RGB light drive
  • 10.MPU6050 raw data acquisition
  • 11.MPU6050 data fusion
  • 12.K210 vision recognition module
  • 13.K230 vision recognition module
6.Smart car course
  • 1.1 Car line tracking-8 channel infrared tracking sensor module
  • 1.2 Car line tracking-4 channel infrared tracking sensor module
  • 2.1 Drawing a circle-8 channel infrared tracking sensor module
  • 2.2 Drawing a circle-4 channel infrared tracking sensor module
  • 3.Ultrasonic following
  • 4.Ultrasonic avoid
  • 5.Ultrasonic avoid(Servo PTZ)
  • 6.Infrared sensor avoid
  • 7.Light following
  • 8.Gyroscope calibration straight-line walk
  • 9.Infrared remote control
  • 10.Autonomous driving car
7.Vision application course
  • 1.K210 autonomous driving
  • 2.K210 color tracking
  • 3.K210 handwritten digit action
  • 4.K210 color response
  • 5.K210 road sign indication action
  • 6.K210 following machine code
  • 7.K210 QR code command
  • 8.K230 vision line tracking
  • 9.K230 color tracking
  • 10.K230 machine code tracking
  • 11.K230 QR code command
  • 12.K230 autonomous avoid
  • 13.K230 license plate tracking
  • 14.K230 face tracking
  • 15.K230 gaze direction tracking
  • 16.K230 palm tracking
  • 17.K230 target tracking
  • 18.K230 human body tracking
  • 19.K230 OCR character recognition
8.Extended application course (Sold separately)
  • 1.Voice interaction module communication
  • 2.Voice interaction control
  • 3.K230 road sign indication action(Voice)
  • 4.K230 color response(Voice)
  • 5.K230 gesture control(Voice)
  • 6.K230 rock-paper-scissors(Voice)
  • 7.8-channel grayscale color line tracking
  • 8.Bluetooth remote control
  • 9.K210 Scenario-based autonomous driving
  • 10.K230 Scenario-based autonomous driving
Download
  • Code
  • SCH
  • 3D Model File
  • MSPM0 Data Sheet
  • Voice firmware
  • Hardware interface manual
Download ZIP

Welcome to MSPM0 Smart Robot Car repository

2.K210 color tracking

K210 Color Tracking

K210 Color Tracking1. Hardware Connection2. Code Analysis3. Main Functions4. K210 Method for Extracting Specified Color LAB Thresholds5. K210 Program Burning6. Experimental Phenomena

1. Hardware Connection

K210 Vision ModuleMSPM0G3507
5V5V
GNDGND
RXTX2
TXRX2

Physical Connection

image-removebg-preview

Schematic Diagram

image-20251029164049976

image-20251029164030395

image-20251029164356332

2. Code Analysis

Control Principle

K210 Protocol

Experiment RoutineStart SymbolLengthRoutine NumberRoutine GroupData AmountxSeparatorySeparatorwSeparatorhSeparatorChecksumEnd Symbol
Color Recognition$XX01BB04XXX,XXX,XXX,XXX,XX#

Control Flow Chart

No
Yes
No
Yes
Start
Vision module detects threshold color
Car stationary
Detected color block in center?
MCU parses data and controls car response

bsp_k210_use.c

xxxxxxxxxx
// 处理K210发来的单字节数据 / Process single byte data from K210
void recv_k210msg(uint8_t recv_msg) 
{
    // 检测包头'$',开始接收新消息 / Detect packet header '$', start receiving new message
    if (recv_msg == '$')
    {
        new_flag = 1;
    }
    
    // 检测包尾'#',结束接收并校验 / Detect packet tail '#', end reception and verify
    if(recv_msg == '#' )
    {
        if( buf_len == r_index)  // 数据长度匹配 / Data length matches
        {
            new_flag = 0;
            tou_flag = 0;
            len_flag = 0;
            
            // 校验和计算:减去接收的校验和字节 / Checksum calculation: subtract received checksum byte
            buf_crc -= buf_msg[r_index-1];
            buf_crc %= 256;
            
            if(buf_crc == buf_msg[r_index-1])  // 校验正确 / Checksum correct
            {
                deal_recvmsg();  // 处理接收数据 / Process received data
            }
            else  // 校验失败 / Checksum failed
            {
                r_index = 0;
                buf_crc = 0;
            }
        }
    }
    
    // 正在接收新消息时的处理逻辑 / Processing logic when receiving new message
    if(new_flag == 1 )
    {
        // 首次接收包头 / First time receiving packet header
        if(recv_msg == '$' && tou_flag == 0)  
        {
            tou_flag = 1;
        }
        else
        {
            // 存储数据并递增索引 / Store data and increment index
            buf_msg[r_index++] = recv_msg; 
            buf_crc += recv_msg;            
            // 未获取长度时,从首字节读取长度 / When length not obtained, read length from first byte
            if(len_flag == 0)  
            {
                buf_len = buf_msg[0];
                len_flag = 1;
            }
        }
    }
}
​
// 解析接收的完整消息 / Parse received complete message
void deal_recvmsg(void)
{
    //长度校验 / Length verification
    if(r_index!=buf_len)
    {
        buf_len = 0;
        return ;
    }
    
    // 提取有效数据(过滤逗号) / Extract valid data (filter commas)
    for(index = 0 ;index<number;index++)
    {
        if(buf_msg[4+index] == 0x2c && i_duo ==0)//遇到逗号且未过滤 / Encounter comma and not filtered
        {
            i_duo = 1;
            continue;
        }
        data[data_i++]=buf_msg[4+index];//存储有效数据 / Store valid data
        i_duo =0;
    }
    
    // 重置接收状态 / Reset receive state
    buf_crc = 0;
    r_index = 0;
    memset(buf_msg,0,sizeof(buf_msg));
    // 处理解析后的数据 / Process parsed data
    deal_data(eg_num);  

k210部分源码

xxxxxxxxxx
# 数据发送函数(按自定义串口协议封装坐标、尺寸和消息,生成可直接发送的完整协议帧) / Data sending function (encapsulates coordinates, dimensions and messages according to custom serial protocol, generates complete protocol frame ready for sending)
​
def send_data(x, y, w, h, msg):
    start = 0x24          # 帧头(对应ASCII字符'$'),标识协议帧的开始 / Frame header (corresponds to ASCII character '$'), marks start of protocol frame                     
    end = 0x23            # 帧尾(对应ASCII字符'#'),标识协议帧的结束 / Frame footer (corresponds to ASCII character '#'), marks end of protocol frame
    length = 5            # 基础长度(初始值=5,包含后续4个固定字段+1个校验位占位) / Base length (initial value=5, contains 4 fixed fields + 1 checksum placeholder)   
    class_num = 0x01      # 例程编号(固定为0x01,与接收端约定的功能标识,颜色识别) / Routine number (fixed as 0x01, function identifier agreed with receiver, color recognition)
    class_group = 0xBB    # 例程组(固定为0xBB,与接收端约定的功能分类标识) / Routine group (fixed as 0xBB, function group identifier agreed with receiver)
    data_num = 0x00       # 数据量(初始为0,后续统计实际封装的数据元素个数) / Data amount (initial 0, will count actual encapsulated data elements later)
    fenge = 0x2C          # 分隔符(对应ASCII字符','),用于区分不同数据段,方便接收端解析 / Separator (corresponds to ASCII character ','), used to distinguish different data segments for easy receiver parsing                     
    crc = 0               # 校验和(初始为0,用于验证数据完整性,防止传输错误) / Checksum (initial 0, used to verify data integrity and prevent transmission errors)                           
    data = []             # 数据列表(存储待封装的坐标、尺寸、消息等实际数据) / Data list (stores actual data to be encapsulated like coordinates, dimensions, messages)
    ...
    if x == 0 and y == 0 and w == 0 and h == 0:
        pass
    else:
        # 封装x坐标(小端模式:低位字节在前,高位字节在后) / Encapsulate x coordinate (little-endian: low byte first, high byte second)
        low = x & 0xFF          # 取x的低8位 / Get low 8 bits of x
        high = x >> 8 & 0xFF    # 取x的高8位 / Get high 8 bits of x
        data.extend([low, fenge, high, fenge])  # 按「低位,高位,」格式添加到数据列表 / Add to data list in "low,high," format
        low = y & 0xFF
        high = y >> 8 & 0xFF
        data.extend([low, fenge, high, fenge])
​
        low = w & 0xFF
        high = w >> 8 & 0xFF
        data.extend([low, fenge, high, fenge])
​
        low = h & 0xFF
        high = h >> 8 & 0xFF
        data.extend([low, fenge, high, fenge])
​
    # 若消息不为空,遍历字符并转换为十进制后封装 / If message not empty, iterate through characters and convert to decimal before encapsulation
    if msg is not None:
        for i in range(len(msg)):
            hec = str_int(msg[i])  # 调用str_int函数,将单个字符转为十进制 / Call str_int function to convert single character to decimal                        
            data.extend([hec, fenge]) 
    data_num = len(data)              # 更新数据量(数据列表的元素总数) / Update data amount (total elements in data list)
    length += data_num                # 更新总长度(基础长度+数据列表长度) / Update total length (base length + data list length)              
    # 组装核心数据段(不含帧头、帧尾、校验和的中间数据) / Assemble core data segment (middle data excluding frame header, footer, checksum)
    send_merr = [length, class_num, class_group, data_num] 
     # 添加实际数据 / Add actual data                                                     
    send_merr.extend(data)                                 
​
    # 计算校验和(对核心数据段所有元素求和,对256取模确保结果在0-255范围) / Calculate checksum (sum all elements of core data segment, modulo 256 to ensure result in 0-255 range)
    for i in range(len(send_merr)):
        crc += send_merr[i]
    crc = crc % 256
    # 组装完整协议帧(帧头 + 核心数据段 + 校验和 + 帧尾) / Assemble complete protocol frame (frame header + core data segment + checksum + frame footer)
    send_merr.insert(0, start)         
    send_merr.append(crc)                   
    send_merr.append(end)
 ...   
# 定义颜色阈值(LAB格式) / Define color thresholds (LAB format)
red_threshold = (30, 100, 40, 80, 10, 70)
green_threshold = (50, 70, -55, -35, 10, 30)
blue_threshold = (35, 74, -128, 53, -65, -20)
# 目标颜色阈值(初始使用红色) / Target color threshold (initially use red)
target_threshold = list(red_threshold)

3. Main Functions

Color_Trace

Function Prototypevoid Color_Trace(int x, int y, int w, int h)
Function DescriptionTarget tracking control function based on color recognition: when target area width and height are not 0, applies first-order low-pass filtering to target center X coordinate and area, calculates X direction (left-right) position deviation and Y direction (forward-backward) area deviation, after PID calculation and limiting, controls car movement through Motion_Car_Control; if target area width and height are 0, stops car
Input Parametersx: Target area top-left X coordinate
y: Target area top-left Y coordinate
w: Target area width
h: Target area height
Return ValueNone

BSP_Loop

Function Prototypevoid BSP_Loop(void)
Function DescriptionMain loop function: enables motor control, displays x, y, w, h parameters of k210_msg on OLED, calls Color_Trace function to implement color tracking control based on target area parameters
Input ParametersNone
Return ValueNone

4. K210 Method for Extracting Specified Color LAB Thresholds

After connecting to CanMV IDE via micro USB, drag follow_color_k210.py to CanMV IDE to open it, then need to first click the run button, ensure the color to be recognized appears in the frame buffer, here using red as an example, click menu bar Tools -> Machine Vision -> Threshold Editor, get image from frame buffer

image-20251029204408672

image-20251029204957872

You can manually drag the slider positions to adjust thresholds, white pixels are tracked, finally fill in the LAB thresholds to our color thresholds

image-20251029205301117

image-20251029205546204

5. K210 Program Burning

After downloading and opening CanMV IDE, we need to first drag the follow_color_k210.py file from the k210 source code provided in this course to CanMV IDE to open it, then connect the IDE, here using helloworld.py as example

image-20251029180540342

After successful IDE connection, the phenomenon is as follows

image-20251029181342135

Here we use helloworld.py as an example, open the top menu bar Tools -> Save currently open script as (main.py) to CanMV Cam

image-20251029205906069

image-20251029181630720

Both Yes/No can be selected here. When the following status appears, the write is successful.

image-20251029181701230

6. Experimental Phenomena

After burning the program, the car will follow red color blocks by default. When the color is far from the car, the car moves forward; when the color is close to the car, the car moves backward; when the color moves left/right, the car also follows left/right, keeping the recognized color in the center of the screen. It is recommended not to move the color block too quickly, otherwise it may leave the recognition area.

K210 autonomous driving
K210 handwritten digit action

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文