yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
STM32-BoardCar📖
0. Get started quickly
  • 0.ReadMe
  • 1. Installation Instructions
  • 2. Version configuration
  • 3. Smart car installation video
  • 4. Precautions for use
1. Introduction to STM32 development board
  • 1. Learn about STM32
  • 2. Introduction to STM32 development board
  • 3. Development board pin assignment
  • 4. Introduction to HAL library and LL library
2. Setting up and using the development environment
  • 1. Common development tools
  • 2. STM32CubeMX Install - Use
  • 3. STM32CubeIDE Install - Use
  • 4. Common Driver Installation
  • 5. Program download and simulation
  • 6. Engineering experience and migration
3. Development board basic tutorial
  • 1. RGB searchlight (GPIO)
  • 2. Buzzer control (GPIO)
  • 3. Button control (EXTI)
  • 4. Serial communication (UASRT)
  • 5. Voltage detection (ADC)
  • 6. Internal temperature sensor(ADC)
  • 7. Independent watchdog(IWDG)
  • 8. Window watchdog(WWDG)
  • 9. Basic timer (TIM6)
  • 10. Universal Timer (TIM3)
  • 11. Advanced timers (TIM1)
  • 12. I2C Communication (IIC)
  • 13. Off-chip Flash (SPI)
  • 14. On-chip Flash (Flash)
  • 15. DMA:USART
  • 16. DMA:SPI
  • 17. DMA:I2C
  • 18. USB communication
  • 19. USB analog U disk
  • 20. FreeRTOS
4. Car expansion tutorial
  • 1. Servo control
  • 2. Basic use of ultrasonic steering gear gimbal
  • 3. Motor control
  • 4. OLED display light sensitivity value
  • 5. Infrared sensor
  • 6. Four-way tracking module
  • 7. Infrared remote control
  • 8. Ultrasonic ranging
  • 9. PS2 controller test
  • 10.K230 Vision Module
  • 11.AI voice interaction integration module
5. Robot car tutorials
  • 1. Car line patrol
  • 2. Ultrasonic follow
  • 3. Ultrasonic obstacle avoidance
  • 4. Ultrasonic obstacle avoidance (servo gimbal version)
  • 5. Infrared sensor obstacle avoidance
  • 6. Infrared remote control
  • 7. PS2 handle remote control
  • 8.K230 face tracking on PTZ
  • 9.K230 color tracking
  • 10.K230 Color Line Patrol
  • 11.K230 QR code command
  • 12.K230 machine code tracking
  • 13.K230 road sign indication action (voice)
  • 14.K230 color response (voice)
  • 15.K230 gesture control (voice)
  • 16.K230 Rock-Paper-Scissors Game (Voice)
6. Operation video
  • 1-How to install STM32CubeIDE software
  • 2-How to create Demo project
  • 3-How to download code into STM32 robot car
  • 4-How to open and compile a code file for STM32
  • 5-About IR control and Charge battery
Download
  • Code
  • SCH
  • Software File
  • STM32 Chip DataSheet
  • Installation manual
Download ZIP

Welcome to STM32-BoardCar repository

9.K230 color tracking

K230 Color Tracking

K230 Color Tracking1. Software - Hardware2. Brief Principle3. Main Functions4. Partial Code Explanation5. Experimental Phenomenon

This tutorial is a comprehensive experiment combining multiple peripherals. You can understand each individual peripheral first before conducting this experiment.

1. Software - Hardware

  • STM32F103CubeIDE

  • STM32 Robot Development Board

    • K230 module: External connection

  • Type-C data cable or ST-Link

    • Used for program downloading or simulation of the development board

2. Brief Principle

Hardware Schematic Diagram

2023103102

Physical Connection Diagram

  • Motor Wiring

    • 2023103106

  • K230 Wiring

    • PixPin_2025-06-10_19-15-08

Control Principle

  • Program Flowchart

    Yes
    No
    Start
    Learn the color threshold of the target area
    Is the target color detected by K230?
    K230 sends data according to the specified protocol
    The car stops
    The single-chip microcomputer parses the data and controls the car to make a feedback
ModuleFunction
K230 Vision ModuleRecognize colors and send data to the microcontroller through the serial port

Communication Protocol:

After the K230 recognizes the color track, it will send a data frame through the serial port with the following format:

Experimental RoutineStart SymbolLengthSeparatorRoutine NumberSeparatorxSeparatorySeparatorwSeparatorhEnd Symbol
Color Recognition$XX,01,XXX,XXX,XXX,XXX#

Microcontroller part:

Receive the data sent by the K230 through the serial port and process each byte of the data. Extract the valid data from the data frame content and store it in an array. Then process the array data, and the microcontroller drives the motor to move according to the processed data.

3. Main Functions

Function: Pto_Data_Parse

Function Prototypevoid Pto_Data_Parse(uint8_t *data_buf, uint8_t num)
FunctionParse the data information returned by the K230
Input Parameter 1Pointer to the array that receives the data
Input Parameter 2Size of the received data
Return ValueNone

Function: Car_Move

Function Prototypevoid Car_Move(void)
FunctionLogic control for the car's tracking
Return ValueNone
For the underlying driver, you can refer to [Chapter 3: Advanced Timer Tutorial] and [Chapter 4: Motor Control Tutorial].
For the application layer, you can read the source code in the project files by yourself.

4. Partial Code Explanation

  • yb_protocol.c

// Protocol parsing function
void Pto_Data_Parse_K230(uint8_t *data_buf, uint8_t num)
{
    uint8_t pto_head = data_buf[0];
    uint8_t pto_tail = data_buf[num - 1];
    if (!(pto_head == PTO_HEAD && pto_tail == PTO_TAIL)) {
        return;
    }

    uint8_t data_index = 1;
    uint8_t field_index[PTO_BUF_LEN_MAX1] = {0};
    int i = 0;

    // Parse the comma separator
    for (i = 1; i < num - 1; i++) {
        if (data_buf[i] == ',') {
            data_buf[i] = 0;
            field_index[data_index] = i;
            data_index++;
        }
    }

    // Handle the case of a pure string without commas - Road sign recognition
    if (data_index == 1) {
        uint8_t len = num - 2;
        memcpy(lubiao, (char*)data_buf + 1, len);
        lubiao[len] = '\0';  // Ensure the string ends with '\0'
    }
    else { // Handle multi-field data
        for (i = 0; i < data_index; i++) {
            uint8_t start = field_index[i] + 1;
            uint8_t len;
            
            if (i == data_index - 1) {
                // For the last field, calculate the length up to before the tail marker
                len = (num - 1) - start;
            } else {
                // For middle fields, the length is the next separator position minus the current start position
                len = field_index[i + 1] - start;
            }
            
            if (i == 6 && data_index == 7) {
                memcpy(msg, (char*)data_buf + start, len);
                msg[len] = '\0';  // Add the string terminator
            }
            else if (i == 2 && data_index == 3) {
                memcpy(game, (char*)data_buf + start, len);
                game[len] = '\0';  // Add the string terminator
            }
            else {
                values1[i] = Pto_Char_To_Int((char*)data_buf + start);
            }
        }
        
        // Protocol length verification
        uint8_t pto_len = values1[0];
        if (pto_len != num) {
            printf("pto_len error:%d , data_len:%d\n", pto_len, num);
            return;
        }


        pto_id = values1[1];
    }
   int x = values1[2];
   int y = values1[3];
   int w = values1[4];
   int h = values1[5];
//    //int degress = values[7];
// //  Uncomment during debugging
 printf("dmcode:x:%d, y:%d, w:%d, h:%d,\n", x, y, w, h);
     // printf("msg:%s\n", game);
//     //  printf("game:%d\n", pto_id
    // Debug output
   // printf("msg:%s\n", msg);
}
  • app_motor.c

xxxxxxxxxx
// Control the movement status of the car.
// Speed control: speed = 0 - 1000.
void wheel_State(uint8_t state, uint16_t speed)
{
    g_speed_setup = speed;
    switch (state)
    {
    case MOTION_STOP:
        g_speed_setup = 0;
        Motion_Stop(speed == 0 ? STOP_FREE : STOP_BRAKE);
        break;
    case MOTION_RUN:
        wheel_Ctrl(speed, 0, 0);
        break;
    case MOTION_BACK:
        wheel_Ctrl(-speed, 0, 0);
        break;
    case MOTION_LEFT:
     wheel_Ctrl(speed/2, 0, -speed*2);
        break;
    case MOTION_RIGHT:
     wheel_Ctrl(speed/2, 0, speed*2);

        break;
    case MOTION_SPIN_LEFT:
        Motion_Set_Yaw_Adjust(0);
        wheel_Ctrl(0, 0, -speed * 5);
        break;
    case MOTION_SPIN_RIGHT:
        Motion_Set_Yaw_Adjust(0);
        wheel_Ctrl(0, 0, speed * 5);
        break;
    case MOTION_BRAKE:
        Motion_Stop(STOP_BRAKE);
        break;
    default:
        break;
    }
}

  • app_irtracking.c

void Car_Move(void)
{
    // If the detection values are 0, it means no target was detected.
    if(values[4] == 0 || values[5] == 0) {
        wheel_State(0,0); // Stop the car.
        return;          // Stop the car and return.
    }

    // Middle processing logic
    // When the target is centered horizontally and there is a significant height difference from the target area
    else if((fabs((X+(W/2) - MIDDLE_WIDTH))<THRESHOLD)&&fabs(pid_k230.target_area-H)>40)
    {
        // When the target is too small (far from the camera)
        if(H<140)
        {
            // Move forward when the target is near the center vertically
            if(Y<MIDDLE_HEIGHT&&Y>MIDDLE_HEIGHT-THRESHOLD)
                Motion_Set_Speed(100,100,100,100); // Move forward.
            // Move backward when the target is too low
            else if(((Y+(H/2) - MIDDLE_HEIGHT)>THRESHOLD))
                Motion_Set_Speed(-100,-100,-100,-100); // Move backward.
        }
        // When the target is too large (close to the camera)
        else if(H>220)
            Motion_Set_Speed(-100,-100,-100,-100); // Move backward.
    }

    // When the target is too low or significantly below the center
    else if((Y>=0&&Y<=100)||((Y+(H/2) - MIDDLE_HEIGHT)>THRESHOLD))
    {
        Motion_Set_Speed(-150,-150,-150,-150); // Move backward quickly.
    }

    // When the target is significantly above the center
    else if((Y+(H/2) - MIDDLE_HEIGHT)<-THRESHOLD)
    {
        Motion_Set_Speed(100,100,100,100); // Move forward.
    }
    // When the target is significantly to the left of the center
    else if((X+(W/2) - MIDDLE_WIDTH)<-THRESHOLD)
    {
        Motion_Set_Speed(0,0,200,200); // Turn left in place.
    }
    // When the target is significantly to the right of the center
    else if((X+(W/2) - MIDDLE_WIDTH)>THRESHOLD)
    {
        Motion_Set_Speed(200,200,0,0); // Turn right in place.
    }

    // When the target is approximately centered
    else
    {
        Motion_Set_Speed(0,0,0,0); // Stop the car.
    }
}

5. Experimental Phenomenon

After the program is successfully downloaded, turn on the switch, and the K230 will enter the color learning state. Place the color to be tracked in the central area of the screen. The progress of threshold learning will be displayed in the upper - left corner of the K230. After learning is completed, when a color target with the corresponding threshold appears within the camera's range, the car will start to follow the specified color. Since the camera's collection range is limited, do not move too fast; otherwise, the target will go out of the frame and the car will not be able to follow the specified color.

xxxxxxxxxx
For program downloading, you can refer to [Chapter 2: Development Environment Setup and Usage → 2.6 Program Download and Simulation].

K230 Code Burning

Required tools: K230, SD card, CanMV IDE K230

Find the k230_track_recong.py file in the project folder, then drag it to CanMV IDE K230, and then choose to save the opened script as main.py to CanMV.

PixPin_2025-06-10_19-59-03

K230 face tracking on PTZ
K230 Color Line Patrol

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

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文